Skip to content

Instantly share code, notes, and snippets.

@Crystalh
Last active August 29, 2015 13:57
Show Gist options
  • Save Crystalh/9414561 to your computer and use it in GitHub Desktop.
Save Crystalh/9414561 to your computer and use it in GitHub Desktop.
TDD Practices

#TDD Practices

##Bad Practices Patterns that can be improved, or simply bad practices spotted within unit tests.

##PHP

###1) Repetition in all tests. Create a setUp() to handle this:

public function testSomething()
{
    $expectedThing = 'foo';
    $contrib = new BBC_News_Model_Contributor();

    $this->assertEquals($expectedThing, $contrib->getThing());
}

public function testSomeOtherThing()
{
    $expectedSomeOtherThing = 'bar';
    $contrib = new BBC_News_Model_Contributor();

    $this->assertEquals($expectedOtherThing, $contrib->getOtherThing());
} 

###Becomes:

    public function setUp()
    {
        $this->contrib = new BBC_News_Model_Contributor();
    }

    public function testSomething()
    {
        $expectedThing = 'foo';
        $this->assertEquals($expectedThing, $this->contrib->getThing());
    }

etc..

###2) Order of assertions. Expected and Actual in wrong order.

public function testSomething()
{
    $expectedThing = 'BBC News';
    $contrib = new BBC_News_Model_Contributor();

    $this->assertEquals($contrib->getThing(), $expectedThing);
}
Runner output:
--- Expected
+++ Actual
@@ @@
-BBC News
+BBC News 

###Becomes:

public function testSomething()
{
    $expectedThing = 'BBC News';
    $contrib = new BBC_News_Model_Contributor();

    $this->assertEquals($expectedThing, $contrib->getThing());
}
Runner output:
--- Expected
+++ Actual
@@ @@
-BBC News
+BBC News  

###3) Polluting Public Interface of a Class with Setters only used for testing Replace all those setters with Mock objects where it makes sense to do so.

myClassTest.php

public function testGetSetName()
{
    $contrib = new BBC_News_Model_Contributor();

    $contrib->setName('John Major');
    $this->assertEquals('John Major', $this->contrib->getName()); 
}

myClass.php

public function getName()
{
    return $this->name;
}

public function setName($name)
{
    $this->name = $name;
}

...

###Becomes:

myClassTest.php

    public function testGetName()
    {
        $expectedName = 'John Major';
        $contrib = $this->getMockContributor();

        $this->assertEquals($expectedName, $contrib->getName());
    }
...
    public function getMockContributor()
    {
        $contributor = Phake::mock('BBC_News_Model_Contributor');

        Phake::when($contributor)
        ->getName()
        ->thenReturn('Jaz Hands');
        Phake::when($contributor)
        ->getDescription()
        ->thenReturn('BBC News');
        Phake::when($contributor)
        ->getImageUri()
        ->thenReturn('http://news.bbcimg.co.uk/media/images/53008000/jpg/_53008230_lowen.jpg');
        Phake::when($contributor)
        ->getRole()
        ->thenReturn('Chief Loo Inspector');


        return $contributor;
    }

myClass.php

public function getName()
{
    return $this->name;
}

###4) Write tests that are of value In many tests suites:

$this->assertTrue(new myClass() instanceof myClass);

###5) Test name reflects order of operations

public function testGetSetName()
{
    $this->contrib->setName('John Major');
    $this->assertEquals('John Major', $this->contrib->getName());
} 

###Becomes:

    public function testSetGetName()
    {
        $this->contrib->setName('John Major');
        $this->assertEquals('John Major', $this->contrib->getName());
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment