TDD Please - Part 1

Laravel Montréal #6 - February 12th, 2015

Before we start ...

Thanks for comming !

Sponsors

Jobs

Get involved

Test Driven Development

How does TDD work ?

Software development cycle that relies on the repetition of a very short development cycle.

Why ?

The process of TDD

" You can not create quality software without test driven development" - Kristofer Joseph

  • It changes the way you build applications
  • Say goodbye to deployment stress... Make sure you can rely on your code... Continuous Integration and Travis CI
  • Instant documentation for your application
  • Reduce technological debts
  • Speed your development speed & decrease maintenance costs

I find your lack of tests disturbing

Robert Martin

"It has become infeasible for a software developer to consider himself professional if he does not practice test-driven development.

David Heinemeier Hansson

"Don’t force yourself to test-first every controller, model, and view (my ratio is typically 20% test-first, 80% test-after)."

Where to begin ?

A bit of vocabulary

A Unit Test

A very simple test of an isolated piece of functionality.


class Greeter {

    public function greet($tags)
    {
        echo "Hello, World.";
    }

}

	

class PracticeTest extends PHPUnit_Framework_TestCase {

	public function testGreeterGreetsHelloWorld()
	{
		$greeter = new Greeter;
		$this->assertTrue($greeter->greet() === 'Hello, World.');
	}
}

	

A Mock

An objects that allows you to simulate behaviour of another object.


Class Generator {
	public function __construct(File $file) 
	{
		$this->file = $file;
	}

	public function fire() 
	{
		$this->file->put('foo.txt', 'Something here...');
	}
}


	

public function testGeneratesFile() {
    $mockedFile = Mockery::mock('File');
    
    $mockedFile->shouldReceive('exists')
               ->once()
			   ->andReturn(true); 
		
	$generator = new Generator($mockedFile);
    $generator->fire();
}


	

A Stub

An objects with a very specific set of data


public function testRegistrationEmailsUser() {
    $fakeUser = new User();
    $fakeUser->fill(['name' => 'Benjamin Gonzalez', 'email' => 'benjamin.rosell@gmail.com']);
	
	$mockedMailer = Mockery::mock('File');
    $mockedMailer->shouldReceive('exists')
               ->once()
			   ->andReturn(true); 

	$generator = new Mailer($user, );
    $generator->fire();
}


	

Integration testing

If a unit test verifies that code works correctly in isolation, then an integration test will fall on the other end of the spectrum. These tests will flex multiple parts of your application, and typically won’t rely on mocks or stubs.

Acceptance testing

Does this code meet the requirements of the client? Your software can pass all unit, functional, and integration tests, but still fail the acceptance tests, if the client or customer realizes that the feature doesn’t work as they expected.

Pitfalls

Common mistakes in TDD

  • Not knowing what to test...
  • Not being carefull when naming your tests
  • Not using test doubles (stubs and mocks)
  • Micro-design over macro-design
  • Not using your tests at all
  • Focusing too much on code coverage
  • Not emphazising acceptance tests
  • False greens

TDD in Laravel

PHPUnit




    
        
            ./app/tests/
        
    


	

Application Folders

  • app
    • commands
    • config
    • controllers
    • database
    • lang
    • models
    • start
    • storage
    • tests
    • views
    • filters.php
    • routes.php

PHPUnit


class FooTest extends TestCase {

    public function testSomethingIsTrue()
    {
        $this->assertTrue(true);
    }

}


	

TDD Kata

Create a simple String calculator with a method int Add(string numbers). The method can take 0, 1 or 2 numbers, and will return their sum (for an empty string it will return 0). For example "" or "1" or "1,2"

Start with the simplest test case of an empty string and move to 1 and two numbers

Remember to solve things as simply as possible so that you force yourself to write tests you did not think about

Remember to refactor after each passing test

TDD Kata

Allow the Add method to handle an unknown amount of numbers

TDD Kata

Allow the Add method to handle new lines between numbers (instead of commas).

the following input is ok: "1\n2,3" (will equal 6)

the following input is NOT ok: "1,\n" (not need to prove it - just clarifying)

TDD Kata

Support different delimiters. To change a delimiter, the beginning of the string will contain a separate line that looks like this: [delimiter]\n[numbers...],

for example ;\n1;2 should return three where the default delimiter is ; .

he first line is optional. all existing scenarios should still be supported

TDD Kata

Calling Add with a negative number will throw an exception "negatives not allowed" - and the negative that was passed. if there are multiple negatives, show all of them in the exception message/p>