Slide 1

Slide 1 text

@afilina Unit Testing by Example SunshinePHP, Miami - February 4, 2017

Slide 2

Slide 2 text

Anna Filina • Project rescue expert • Dev, trainer, speaker • 1 company • 2 conferences

Slide 3

Slide 3 text

Objectives • Make testing enjoyable. • Make it useful. • Reduce pre-release stress.

Slide 4

Slide 4 text

You Don’t Become an Expert Overnight

Slide 5

Slide 5 text

You Don’t Start With 100% Coverage

Slide 6

Slide 6 text

Testing Without Automation

Slide 7

Slide 7 text

Manually • Check database • var_dump • Only what changed • "Good enough" is subjective

Slide 8

Slide 8 text

Problems • Last-minute bugs • Discovered by customers • Afraid of the code

Slide 9

Slide 9 text

Automated • Control • Discover bugs • Confidence • More features, fewer bugs

Slide 10

Slide 10 text

Shopping Cart

Slide 11

Slide 11 text

Step 1: Found Bug $item = new CartItem("Overwatch", 30); $item->setQuantity(0.1); $this->assertEquals(1, $item->getQuantity());

Slide 12

Slide 12 text

Step 1: Found Bug $item = new CartItem("Overwatch", 30); $item->setQuantity(0.1); $this->assertEquals(1, $item->getQuantity()); public function setQuantity($qty) { $this->qty = ceil($qty); }

Slide 13

Slide 13 text

Too Simple? • Prevent future breaks • Why code is written this way • Same effort as comments

Slide 14

Slide 14 text

Regression Testing

Slide 15

Slide 15 text

Step 2: Improve Code $item = new CartItem("Overwatch", 30); $item->setQuantity(2); $cart->addItem($item); $this->assertEquals(0, $cart->getShipping());

Slide 16

Slide 16 text

Step 2: Improve Code public function getShipping() { if ($this->subtotal >= 40) { return 0; } else { return 15; } }

Slide 17

Slide 17 text

Test Both Cases $item = new CartItem("Overwatch", 30); $item->setQuantity(1); $cart->addItem($item); $this->assertEquals(15, $cart->getShipping());

Slide 18

Slide 18 text

Step 3: New Code public function getTotal() { //... $taxes = $this->getApplicableTaxes(); foreach ($taxes as $tax) { $total += $subtotal * $tax->getPercent(); } //... }

Slide 19

Slide 19 text

Step 3: New Code array (size=2) 0 => array (size=2) 'name' => string 'GST' (length=3) 'percent' => float 0.05 1 => array (size=2) 'name' => string 'QST' (length=3) 'percent' => float 0.09975

Slide 20

Slide 20 text

Step 3: New Code $cart = new Cart(); $taxes = $cart->getApplicableTaxes(); $this->assertInternalType('array', $taxes); $this->assertCount(2, $taxes); $gst = $taxes[0]; $this->assertEquals(0.05, $gst['percent']);

Slide 21

Slide 21 text

Advantages • More tests. • Easy to write. • Never fall too far.

Slide 22

Slide 22 text

Data From CSV

Slide 23

Slide 23 text

Step 4: Before (TDD) $import = new CatalogImport(); $products = $import->parseFromCsv('catalog.csv'); $this->assertInternalType('array', $products); $this->assertCount(2, $products); $this->assertArrayHasKey('name', $products[0]); $this->assertArrayHasKey('price', $products[0]);

Slide 24

Slide 24 text

A New Mindset • Write less code • Stay focused • Elegant code • Works right away

Slide 25

Slide 25 text

Tips • How it’s not supposed to work. • Plan for exceptions. • Focus on realistic scenarios.

Slide 26

Slide 26 text

Don't Waste Time $total = 5; $this->assertNotNull($total);

Slide 27

Slide 27 text

How Many Cases?

Slide 28

Slide 28 text

Cyclomatic Complexity

Slide 29

Slide 29 text

Execution Paths public function getShipping() { if ($this->subtotal >= 40) { return 0; } return $this->shipping; }

Slide 30

Slide 30 text

Condition Loop

Slide 31

Slide 31 text

Zero Times foreach ($products as $product) { $total = $product->price * $product->quantity; } if ($total > 0) { echo 'found'; }

Slide 32

Slide 32 text

Multiple Times $total = 0; foreach ($products as $product) { $total = $product->price * $product->quantity; } if ($total > 0) { echo 'found'; }

Slide 33

Slide 33 text

Recap • Testing takes practice. • Write tests when you see a bug. • Write tests when you improve code.
 • Write tests as you write new code. • Write tests before you write code. • Test unexpected scenarios.

Slide 34

Slide 34 text

Testing =
 Preemptive Debugging

Slide 35

Slide 35 text

@afilina afilina.com joind.in