#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());
}