Unit testing done right
whoami
• Brian Fenton
• Bigcommerce
• @brianfenton
• Mostly PHP and APIs
What is a unit test?
• Small
• Fast
• Tests a single unit <- Here there be dragons
Unit?
It depends…
“A single piece of a class’s
public-facing functionality”
History lesson
Goals of unit testing over
time
• Find bugs
• Find regressions
• Improve design
Philosophies
• Traditional testing
• TDD
• XP
• BDD
Behavior vs. Methods
https://twitter.com/sarahmei/status/633895726993440768
How did we get here?
Code coverage
"When a measure becomes a target, it
ceases to be a good measure.” -
Goodhart’s Law
Different kinds of coverage
• Line
• Function/Method
• Class/Trait
Gresham’s Law
/ht @noahsussman
Coverage tricks
• if (false) this_function_call_is_covered();
• // @codeCoverageIgnore
• multiple checks on the same line
Line coverage can only prove code
wasn’t executed
Opcodes
Example
for	
  ($i	
  =	
  0;	
  $i	
  >	
  10;	
  $i++)	
  {	
  
	
  	
  	
  	
  if	
  ($i	
  %	
  2	
  ===	
  0)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  echo	
  "Even:	
  ";	
  
	
  	
  	
  	
  }	
  else	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  echo	
  "Odd:	
  ";	
  
	
  	
  	
  	
  }	
  
	
  	
  	
  	
  echo	
  $i,	
  "n";	
  
}
More kinds of coverage
• Opcode
• Branch
• Path
Testing your privates
• Don’t!
• Extract functionality to a collaborator or
don’t test it
Don’t test your
implementation
Flaky tests
Flaky tests
• Randomness
• Time/environment
• Network/services
Randomness
• Can the randomness come from outside?
• Do you need to know the exact value?
• Can you just verify “randomness”?
Namespace trick
namespace	
  MyNamespace;	
  
function	
  random()	
  
{	
  
	
  	
  	
  	
  return	
  mt_rand();	
  
}	
  
Namespace trick
namespace	
  MyNamespace	
  {	
  
	
  	
  	
  	
  function	
  random()	
  {	
  return	
  7;	
  }	
  
}	
  
namespace	
  MyTests;	
  
…	
  
function	
  testRandomNumberGenerator()	
  
{	
  
	
  	
  	
  	
  $this-­‐>assertSame(7,	
  random());	
  
}
Environment
• Time
• Shell vars/ini settings/config values
• Filesystem
Network/Services
Good unit tests
• Single reason to fail
• Clearly named
• testGuestCanRegisterWithValidInformation
• testProcessData
Good unit tests
• Easy to read
• Clean
• Arrange, Act, Assert
Good unit tests
• Fast
• No side effects
Listening to your tests
Test smells
• Too many mocks
• Lots of setup required
• Can’t test w/o database/network/etc…
• Can’t inject mocks where needed
Test smells
• Mocks returning mocks
• Flaky results
• Unrelated code changes breaking tests
• Testing the implementation
Questions?
https://joind.in/14721

Unit Testing Done Right