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
“A single piece of a class’s public-facing functionality”
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?
"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
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
• 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 tricknamespace My\Namespace;
function random() { return mt_rand(); }
Namespace tricknamespace My\Namespace { function random() { return 7; } }
namespace My\Tests; … function testRandomNumberGenerator() { $this-‐>assertSame(7, random()); }
Environment
• Time
• Shell vars/ini settings/config values
• Filesystem
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