unit test your code with phpunit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · unit...

27
Unit Test Your Code With PHPUnit Matthew Radcliffe mradcliffe @mattkineme

Upload: others

Post on 30-May-2020

19 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

Unit Test Your Code With PHPUnit

Matthew Radcliffe mradcliffe

@mattkineme

Page 2: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

Software Quality Assurance

• Prevent defects from making it to the customer:

• Adopt standards and specifications

• Review code

• Manage releases

• Test code

Page 3: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

Value of Testing• Increase reliability and quality of software.

• “I didn’t think of that!”

• Discover regressions in software.

• “Why did it break?”

• Improve confidence in our code.

• “I think this will work.”

Page 4: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

Common Complaints Regarding Tests

Writing tests takes too long.Start small. 100% coverage isn’t going to come in a day.

I don’t have source control / version control.

Do not pass go. Do not write any more code. Go directly to a Git repository.

I don’t have any testing infrastructureRun locally, enforce social contract. Or setup TravisCI publicly or privately.

I don’t know what I’m going to write until I write it.

Not everyone needs to adopt Test-Driven Development, but it is “best practice”.

My code is heavily integrated with state (database or web services).

That’s where test doubles come into play, but you may be stuck in similar to Drupal 6-7.

Page 5: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

Some Types of Testing• User Acceptance Test: Test according to specification or

requirement.

• Functional Test: Test one function (or feature) expected output.

• Unit Test: Test the smallest “unit” of testable code (in isolation).

• Integration Test: Test the interaction of “units” in 1 or more systems.

• Behavioral Test: Automated UAT or black box testing.

• Stress Test: Test the product under heavy load/stress.

Page 6: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

Unit Tests• A unit is the smallest testable piece of code, which is often a

function, class or method.

• Plug a set of inputs into that code, and confirm the expected output (like behavioral and integration tests).

• Units should act in memory and not depend on other systems.

• Should be fast.

• Run all unit tests after code change.

Page 7: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

Testing: The Basic Idea

• Fibonacci Sequence [0, 1, 1, 2, 3, 5, … N]

• Given a number assert the correct Fibonacci number in the sequence.

• Inputs: 1, 5, 10, 100

• Output: 0, 8, 55, 354224848179261915075

Page 8: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

1 <?php 2 // fibonacci.php 3 4 // Well I only need to know this up to 5, so why bother? 5 6 function fibonacci($number) { 7 $sequence = [0 => 0, 1 => 1, 2 => 1, 3 => 2, 4 => 5, 5 => 8]; 8 return $sequence[$number]; 9 }

Page 9: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

1 <?php 2 // fibonacciTest.php 3 4 require_once "fibonacci.php"; 5 6 function testFibonacci() { 7 8 // Assert our expected output. 9 var_dump((fibonacci(0) === 0) === TRUE); 10 var_dump((fibonacci(5) === 8) === TRUE); 11 var_dump((fibonacci(10) === 55) === TRUE); 12 var_dump((fibonacci(100) === 354224848179261915075) === TRUE); 13 var_dump((fibonacci(-5) === 5) === TRUE); 14 var_dump((fibonacci(-6) === -8) === TRUE); 15 } 16 17 testFibonacci();

Page 10: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

PHP Test Frameworks• SimpleTest

• Also allows for unit and integration tests in the same framework.

• PHPUnit

• De facto standard for PHP applications and frameworks.

• Annotation-based test discovery and handles testing Exceptions.

• Coverage report with static code analysis.

• Supports introspection for test doubles.

• Travis CI has built-in support.

Page 11: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

PHPUnit: Getting Started

• Composer: composer require phpunit/phpunit:4.8.*

• phpunit.xml

• bootstrap.php

• Test class

• Run it: ./vendor/bin/phpunit

Page 12: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

1 <?xml version="1.0" encoding="UTF-8"?> 2 <phpunit bootstrap="tests/bootstrap.php"></phpunit>

phpunit.xml

Page 13: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

1 <?php 2 3 require_once __DIR__ . "/../fibonacci.php";

tests/bootstrap.php

Page 14: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

1 <?php 2 3 4 class FibonacciTest extends PHPUnit_Framework_TestCase { 5 6 function testFibonacci() { 7 $this->assertEquals(0, fibonacci(0)); 8 $this->assertEquals(8, fibonacci(5)); 9 $this->assertEquals(55, fibonacci(10)); 10 $this->assertEquals(354224848179261915075, fibonacci(100)); 11 $this->assertEquals(5, fibonacci(-5)); 12 $this->assertEquals(-8, fibonacci(-6)); 13 } 14 }

tests/FibonacciTest.php

Page 15: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

PHPUnit: Assertions• assertEquals

• assertEmpty

• assertSame

• assertInstanceOf

• assertXmlStringEqualsXmlFile

• assertArrayHasKey

• assertArrayHasSubset

• assertCount

• assertFileExists

• assertNull

Sebastian Bergmann. PHPUnit Manual. https://phpunit.de/manual/current/en/appendixes.assertions.html

Page 16: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

PHPUnit: Data Providers

• A data provider is a method that returns an array of parameters to pass into a test method.

• A test method may test several inputs.

• Important to note that data provider methods are run before any setup so this cannot depend on any test doubles.

Page 17: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

19 function sequenceProvider() { 20 return [ 21 [0, 0], 22 [5, 8], 23 [10, 55], 24 [100, 354224848179261915075], 25 [-5, 5], 26 [-6, 8] 27 ]; 28 } 29 30 /** 31 * Test class with data provider. 32 * 33 * @dataProvider sequenceProvider 34 */ 35 function testFibonacciWithProvider($number, $expected) { 36 $this->assertEquals($expected, fibonacci($number)); 37 } 38 }

tests/FibonacciTest.php

Page 18: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

PHPUnit: setUp• The setUp method is executed for every test method in a

class.

• Used to configure fixtures or setting up a known state.

• Useful for setting up test doubles or mocks, which are dependencies of a unit that you do not need to test in that test class.

• A complex setUp helps to isolate design problems.

Page 19: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

PHPUnit: Test Doubles• Test doubles (or mock objects) allow to focus an unit test on

the code that needs to be tested without bootstrapping dependencies.

• Example: I don’t want to load Drupal 8’s Entity system when I test my unrelated code. Instead PHPUnit allows to create a mock via Ref lection so that I get an object that looks like an Entity.

• Ref lection or introspection allows a program to know about and modify itself at runtime.

Page 20: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

PHPUnit: Test Doubles• getMockBuilder()

• disableOriginalConstructor(), getMock()

• method()

• with(), withConsecutive()

• callback()

• will(), willReturn()

• onConsecutive(), returnValueMap()

Page 21: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

1 <?php 2 3 4 5 class BlahTest extends PHPUnit_Framework_TestCase { 6 7 protected function setUp() { 8 9 $reader = $this->getMockBuilder('League\Csv\Reader') 10 ->disableOriginalConstructor() 11 ->getMock(); 12 $reader->expects($this->any()) 13 ->method('fetchAll') 14 ->willReturn([ 15 ['john', 'doe', '[email protected]'], 16 ['jane', 'doe', '[email protected]'] 17 ]); 18 19 // Calling $reader->fetchAll() will return the array mocked above. 20 } 21 }

Ignace Nyamagana Butera. CSV. https://github.com/thephpleague/csv/blob/master/src/Reader.php

Page 22: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

Overview of Continuous Integration• Every commit is tested.

• How is this achieved?

• Automated test and build environment.

• What are some of my options?

• Jenkins

• Travis CI

• Bamboo (Atlassian)

• Some other proprietary solution

Page 23: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

Travis CI for Open Source

• Anyone can setup Travis CI for their open source repository on GitHub.

• Go to travis-ci.org, login with github, add your project.

• Add a .travis.yml, validate it, commit, and push.

• Test on PHP 5, 7, HHVM, etc…, add dependencies via composer, and setup databases into your build matrix.

Page 24: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

1 language: php 2 3 php: 4 - 5.4 5 - 5.5 6 - 5.6 7 8 sudo: false 9 10 install: 11 - composer self-update 12 13 before_script: 14 - composer install --prefer-source -n

Customizing The Build. http://docs.travis-ci.com/user/customizing-the-build/

Page 25: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

Putting it all Together

• mradcliffe/pokerhand

• Write a test for Bill Condo’s poker hand feed.

• Refactor code to support that test.

Page 26: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

Code

Page 27: Unit Test Your Code With PHPUnit - softpixelmradcliffe/files/columbusphp-unit-testing.pdf · Unit Tests • A unit is the smallest testable piece of code, which is often a function,

Questions & Challenge

• Twitter: @mattkineme

• GitHub: @mradcliffe

• DrupalCamp Ohio 2015

• 10/23/2015 - 10/24/2015

http://softpixel.com/~mradcliffe/#!/articles