Top Banner
99% IS NOT ENOUGH
42

99% is not enough

Apr 15, 2017

Download

Software

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 99% is not enough

99%IS NOT ENOUGH

Page 2: 99% is not enough

Sebastian Thoß Kruno Knego Sebastian HeuerBackend Lead Backend Developer Developer Advocate

Page 3: 99% is not enough
Page 4: 99% is not enough
Page 5: 99% is not enough
Page 6: 99% is not enough
Page 7: 99% is not enough
Page 8: 99% is not enough

Goods and Bads• fully object-oriented

• easy refactoring thanks to 100% code coverage

• not enough automated acceptance tests

• dependencies to legacy software (database changes, API calls)

Page 9: 99% is not enough
Page 10: 99% is not enough
Page 11: 99% is not enough

Code Coverage

100% != 100%

Page 12: 99% is not enough

public function execute() { $orders = $this->orderService->getOrders($this->orderNumber); $json = $this->orderJsonMapper->map($orders);

return new CommandResult($json); }

Example

Page 13: 99% is not enough

public function testExecute() { $service = $this->createMock(OrderService::class); $mapper = $this->createMock(OrderJsonMapper::class);

$order1 = $this->createMock(Order::class); $order2 = $this->createMock(Order::class);

$command = new GetOrdersCommand('123', $service, $mapper);

$service->expects($this->once()) ->method('getOrders') ->with('123') ->willReturn([$order1, $order2]);

$mapper->expects($this->once()) ->method('map') ->with([$order1, $order2]);

$command->execute(); }

Page 14: 99% is not enough

100%!

Page 15: 99% is not enough

public function execute() { $orders = $this->orderService->getOrders($this->orderNumber); $json = $this->orderJsonMapper->map($orders);

return new CommandResult(json_encode('{"foo":"bar"}')); }

Breaking Stuff

Page 16: 99% is not enough

Still 100%!

Page 17: 99% is not enough

Test Pyramid

UNIT TESTS

Page 18: 99% is not enough

Unit Testing leads to SOLID(ish) code• Single Responsibility

• Open/Closed

• Liskov Substitution

• Interface Segregation

• Dependency Inversion

Page 19: 99% is not enough
Page 20: 99% is not enough

Test Pyramid

INTEGRATION TESTS

UNIT TESTS

Page 21: 99% is not enough

Class 1 Class 2

Class 3Mock

Integration Test

Page 22: 99% is not enough

Test Pyramid

ACCEPTANCE TESTS

INTEGRATION TESTS

UNIT TESTS

Page 23: 99% is not enough

Class 1 Class 2

Class 3

Acceptance Test

Page 24: 99% is not enough

Test Pyramid

ACCEPTANCE TESTS

INTEGRATION TESTS

UNIT TESTS

?

$$$

¢

Page 25: 99% is not enough
Page 26: 99% is not enough

<?php namespace Kartenmacherei\Phpughh;

use PHPUnit_Framework_TestCase;

class SmokeTest extends PHPUnit_Framework_TestCase { /** * @dataProvider furyUrlProvider * * @param Url $url */ public function testFuryUrl(Url $url) { $result = $this->sendGetRequest($url);

$this->assertSame(200, $result->getStatusCode()); $this->assertNotEmpty($result->getBody()); $this->assertLessThanOrEqual(100, $result->getTimeToFirstByteInMilliseconds()); }

Page 27: 99% is not enough

Test Pyramid

ACCEPTANCE TESTS

INTEGRATION TESTS

UNIT TESTS

SMOKE TESTS

$$$

¢

Page 28: 99% is not enough

Test Pyramid

ACCEPTANCE TESTS

INTEGRATION TESTS

SMOKE TESTS

92% COVERAG

E

UNIT TESTS

Page 29: 99% is not enough

Test Pyramid

ACCEPTANCE TESTS

INTEGRATION TESTS

SMOKE TESTS

UNIT TESTS

100% COVERAG

E

Page 30: 99% is not enough

Why 100%?

Page 31: 99% is not enough

Why 100%?• Robustness

• Feeling of security when refactoring

• Fixing bugs is cheaper

• Reducing amount of major bugs found in production

• Broken Windows Theory

Page 32: 99% is not enough

"Factory Denver5" by dliban licensed under CC BY-NC-ND 2 - https://flic.kr/p/73y9dg

Page 33: 99% is not enough

"Factory Denver5" by dliban licensed under CC BY-NC-ND 2 - https://flic.kr/p/73y9dg

Page 34: 99% is not enough

But what about…

• Setters?

• Factories?

• Trivial Classes?

Page 35: 99% is not enough

Tips & Tricks

Page 36: 99% is not enough

Strict PHPUnit Config<?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.6/phpunit.xsd" bootstrap="bootstrap.php" backupGlobals="false" backupStaticAttributes="false" beStrictAboutChangesToGlobalState="true" beStrictAboutOutputDuringTests="true" beStrictAboutTestsThatDoNotTestAnything="true" forceCoversAnnotation="true" beStrictAboutCoversAnnotation="true">

Page 37: 99% is not enough

Mocking public function testCalculatorMultiplies() { $multiplier = $this->getMultiplierMock(); $calculator = new Calculator($multiplier); // (…) }

/** * @return PHPUnit_Framework_MockObject_MockObject|Multiplier */ private function getMultiplierMock() { return $this->createMock(Multiplier::class); }

Page 38: 99% is not enough

@codeCoverageIgnore

• errorHandlers

• shutdownHandlers

Be very strict about excluding code from coverage!

Page 39: 99% is not enough

@codeCoverageIgnoreBe very strict about excluding code from coverage!

/** * @param mixed $targetNode * * @throws WrongInstanceException */ private function ensureIsElement($targetNode) { if (!$targetNode instanceof fDOMElement) { // @codeCoverageIgnoreStart throw new WrongInstanceException('target node is not instance of fDOMElement'); // @codeCoverageIgnoreEnd } }

Page 40: 99% is not enough

Don't test your privates!

• Uncovered private methods are probably obsolete

• "If covering private methods by only testing public methods is hard, there might be another class in there struggling to get out"

Page 41: 99% is not enough

"Who's going to pay for all that?"Re

lative

Cost

of a B

ugfix

40x

80x

120x

160x

Requirements Design Code Developer Tests Acceptance Tests Operations

1x 5x 10x20x

50x

150x

Source: Barry Boehm, Keynote Address, EQUITY 2007.

Page 42: 99% is not enough

https://www.instagram.com/kartenmacherei/

Q&A

https://www.facebook.com/kartenmacherei/ +49 40 468996861

[email protected]

http://www.kartenmacherei.de/recruiting