Effective Unit Testing
You Are Here
Me
Experience: 1 year QA (ManualScripting)
3 years Automation (InfraCI)
5 years Developer (UnitIntegration)
2 years Team Lead (Process)
(+) Positive: Eager to argue
(-) Negative: Perfectionism
Hobbies: Happy Hours
Testing
Eyal Kenig
Team Lead
● Test Pyramid
● Benefits (of good test suites)
● Test Schema (How a test should look like?)
● Tips
● Guidelines by examples
● More.. if we’ll have time
Agenda
Test Pyramid
Benefits
● Confidence
○ A bug is either a requirement change or an integration issue
● Better Design
○ Writing your test is the first “code review” on your code
● Requirements
○ Business logic is documented in the tests
● Robustness
○ The ability of a system to resist change
● Code smells
○ are easily identifiable when writing or reading tests
...of good unit tests
Test Schema
● Test name (description) Subject Scenario Result
○ SetTimeFrame_EndDateSmallerThanStartDate_RaiseAnException
○ Describe(“SetTimeFrame”,
it(“should raise an exception if end date is smaller than start
date”...
● A Test has only one assert
● A Test body has 3 distinct parts
○ Arrange
○ Act
○ Assert
OR ● Arrange
● Expect
● Act
When a test fails...
What is the fastest way to understand what's wrong?
Reading the test name  description
Reading the error produced by the test
Looking at its single assertion
Reading the body of the test
Debugging it
Pro Tips
Use this order and importance when writing tests for public method:
1. Return Values
○ Test for the possible return values of the methods
2. Exceptions
○ Test what happens if each line throws an exception
3. Edge Cases
○ Nil values, empty string, empty arrays, etc..
4. External Dependencies
○ Do I Call my external dependencies with the correct arguments?
Test the interface! Only public functions should be tested.
(private functions are implementation details and not requirements)
TRADEOFFS
Pro Tips
Ask Yourself..
● For each test
○ What’s the meaning of this test failing?
○ How could I understand what’s wrong when this test will fail?
○ Which change in your code will cause this test to fail?
● For each test suite
○ Can the tests run asynchronously?
○ Is this suite coverage the most important aspects of the component?
○ When a change will be needed - how easy it would be to change these tests?
Pro Tips
● It’s better to delete bad tests than keeping them
○ They’ll waste you more time in maintenance, while producing a low value (ROI)
○ If you can’t trust them, you’d probably run them a few times before actually checking if
something is wrong
○ Tests tends to get duplicated
● A bad test is..
○ One that sometime fails.
○ One that contact an actual external service.
○ One that is testing the code itself and not its meaning.
○ One that takes too much time.
Pro Tips
● As a code reviewer:
○ Start from the tests (sometimes)
○ Skip the arrangement part - read only:
■ Description
■ Action
■ Assertion
○ Now go over the class
■ Are there important aspects that were missing in the tests?
● As a code reviewee:
○ Write the tests before the code review
○ Not sure about the solution?
■ Advice before code review
Guidelines By Example
● Don’t be too specific - Otherwise it’ll hurt your ability to change.
Calling only once - could make
sense, but if it's important -
maybe we should write it in a
dedicated test?
Guidelines By Example
● Don’t be too defensive - if you tested the case elsewhere, you know it works.
Guidelines By Example
● Don’t be too defensive - if you tested the case elsewhere, you know it works.
Only One Assert
Guidelines By Example
● Prefer readability over DRY - a test should be understandable solely from its body.
Guidelines By Example
● Test the requirements - and not how you implement it.
test name implies “how” we normalize
Help the
reader with
a result that
make sense
Bad Practices
● Fixtures
○ State is shared between multiple test suites
● VCR Cassettes
○ What will you do when a call will change?
● Mocking the class under test
○ You are testing a class that feels like your class, but it isn’t.
● Using meaningless name
○ What bob_account stands for?
Both force you to go
to other files to
understand the case
of the test
Pro Tips
● Separate bad interfaces from your logic
○ If a library you use is not easy to test - move it to another class.
Often, you will see that it was the best design in the first place.
● Always create a test file
○ Next time something will change a test wouldn’t be added, and it's a slippery slope.
● Fail the test!
○ To ensure you’ve actually tested what you meant.
● When a production bug is found, a new test is born
○ Run the test before the fix, and after
Takeaways
● It’s easy to improve unit tests skills
● Put your effort in writing better tests to gain more ROI
● Pay attention to smells like “it cannot be tested”
● Now that you have the best tests - Refactor away!
Pssst… There are more tips after this slide!
Guidelines for Good Walkers
● Avoid cascading failures - if all the tests fail together, could you tell what's wrong?
● Test only the requirement - switch entire implementation without affecting the tests.
● Use basic lingo - Fancy coding skills will harm readability.
● Prefer readability over performance - but don’t exaggerate.
● Don’t test providers - But keep them without any logic.
● Keep setup small - only REAL shared steps should be there.
● Be Precise - prepare exactly what is need, not more, nor less.
● Assume external dependencies are OK - but.. There are some exceptions
Thank You.
Reference
● The Rails Testing Pyramid http://blog.codeclimate.com/blog/2013/10/09/rails-testing-pyramid/
● Writing Great Unit Tests: Best and Worst Practices
http://blog.stevensanderson.com/2009/08/24/writing-great-unit-tests-best-and-worst-practises/
● Martin Fowler
○ UnitTest https://martinfowler.com/bliki/UnitTest.html
○ Testing Strategies in a Microservice Architecture
https://martinfowler.com/articles/microservice-testing
● Boundaries - A talk by Gary Bernhardt https://www.destroyallsoftware.com/talks/boundaries
● Jay Fields on Working Effectively with Unit Tests -
http://www.se-radio.net/2016/05/se-radio-episode-256-jay-fields-on-working-effectively-with-unit-test
s/
● XUnit Test Patterns - http://xunitpatterns.com/index.html
● Tautoloy Tests - https://medium.com/@rowillia/tautology-tests-7dabd81ade30

Effective Unit Testing

  • 1.
  • 2.
    Me Experience: 1 yearQA (ManualScripting) 3 years Automation (InfraCI) 5 years Developer (UnitIntegration) 2 years Team Lead (Process) (+) Positive: Eager to argue (-) Negative: Perfectionism Hobbies: Happy Hours Testing Eyal Kenig Team Lead
  • 3.
    ● Test Pyramid ●Benefits (of good test suites) ● Test Schema (How a test should look like?) ● Tips ● Guidelines by examples ● More.. if we’ll have time Agenda
  • 4.
  • 5.
    Benefits ● Confidence ○ Abug is either a requirement change or an integration issue ● Better Design ○ Writing your test is the first “code review” on your code ● Requirements ○ Business logic is documented in the tests ● Robustness ○ The ability of a system to resist change ● Code smells ○ are easily identifiable when writing or reading tests ...of good unit tests
  • 6.
    Test Schema ● Testname (description) Subject Scenario Result ○ SetTimeFrame_EndDateSmallerThanStartDate_RaiseAnException ○ Describe(“SetTimeFrame”, it(“should raise an exception if end date is smaller than start date”... ● A Test has only one assert ● A Test body has 3 distinct parts ○ Arrange ○ Act ○ Assert OR ● Arrange ● Expect ● Act
  • 7.
    When a testfails... What is the fastest way to understand what's wrong? Reading the test name description Reading the error produced by the test Looking at its single assertion Reading the body of the test Debugging it
  • 8.
    Pro Tips Use thisorder and importance when writing tests for public method: 1. Return Values ○ Test for the possible return values of the methods 2. Exceptions ○ Test what happens if each line throws an exception 3. Edge Cases ○ Nil values, empty string, empty arrays, etc.. 4. External Dependencies ○ Do I Call my external dependencies with the correct arguments? Test the interface! Only public functions should be tested. (private functions are implementation details and not requirements)
  • 9.
  • 10.
    Pro Tips Ask Yourself.. ●For each test ○ What’s the meaning of this test failing? ○ How could I understand what’s wrong when this test will fail? ○ Which change in your code will cause this test to fail? ● For each test suite ○ Can the tests run asynchronously? ○ Is this suite coverage the most important aspects of the component? ○ When a change will be needed - how easy it would be to change these tests?
  • 11.
    Pro Tips ● It’sbetter to delete bad tests than keeping them ○ They’ll waste you more time in maintenance, while producing a low value (ROI) ○ If you can’t trust them, you’d probably run them a few times before actually checking if something is wrong ○ Tests tends to get duplicated ● A bad test is.. ○ One that sometime fails. ○ One that contact an actual external service. ○ One that is testing the code itself and not its meaning. ○ One that takes too much time.
  • 12.
    Pro Tips ● Asa code reviewer: ○ Start from the tests (sometimes) ○ Skip the arrangement part - read only: ■ Description ■ Action ■ Assertion ○ Now go over the class ■ Are there important aspects that were missing in the tests? ● As a code reviewee: ○ Write the tests before the code review ○ Not sure about the solution? ■ Advice before code review
  • 13.
    Guidelines By Example ●Don’t be too specific - Otherwise it’ll hurt your ability to change. Calling only once - could make sense, but if it's important - maybe we should write it in a dedicated test?
  • 14.
    Guidelines By Example ●Don’t be too defensive - if you tested the case elsewhere, you know it works.
  • 15.
    Guidelines By Example ●Don’t be too defensive - if you tested the case elsewhere, you know it works. Only One Assert
  • 16.
    Guidelines By Example ●Prefer readability over DRY - a test should be understandable solely from its body.
  • 17.
    Guidelines By Example ●Test the requirements - and not how you implement it. test name implies “how” we normalize Help the reader with a result that make sense
  • 18.
    Bad Practices ● Fixtures ○State is shared between multiple test suites ● VCR Cassettes ○ What will you do when a call will change? ● Mocking the class under test ○ You are testing a class that feels like your class, but it isn’t. ● Using meaningless name ○ What bob_account stands for? Both force you to go to other files to understand the case of the test
  • 19.
    Pro Tips ● Separatebad interfaces from your logic ○ If a library you use is not easy to test - move it to another class. Often, you will see that it was the best design in the first place. ● Always create a test file ○ Next time something will change a test wouldn’t be added, and it's a slippery slope. ● Fail the test! ○ To ensure you’ve actually tested what you meant. ● When a production bug is found, a new test is born ○ Run the test before the fix, and after
  • 20.
    Takeaways ● It’s easyto improve unit tests skills ● Put your effort in writing better tests to gain more ROI ● Pay attention to smells like “it cannot be tested” ● Now that you have the best tests - Refactor away! Pssst… There are more tips after this slide!
  • 21.
    Guidelines for GoodWalkers ● Avoid cascading failures - if all the tests fail together, could you tell what's wrong? ● Test only the requirement - switch entire implementation without affecting the tests. ● Use basic lingo - Fancy coding skills will harm readability. ● Prefer readability over performance - but don’t exaggerate. ● Don’t test providers - But keep them without any logic. ● Keep setup small - only REAL shared steps should be there. ● Be Precise - prepare exactly what is need, not more, nor less. ● Assume external dependencies are OK - but.. There are some exceptions
  • 22.
  • 23.
    Reference ● The RailsTesting Pyramid http://blog.codeclimate.com/blog/2013/10/09/rails-testing-pyramid/ ● Writing Great Unit Tests: Best and Worst Practices http://blog.stevensanderson.com/2009/08/24/writing-great-unit-tests-best-and-worst-practises/ ● Martin Fowler ○ UnitTest https://martinfowler.com/bliki/UnitTest.html ○ Testing Strategies in a Microservice Architecture https://martinfowler.com/articles/microservice-testing ● Boundaries - A talk by Gary Bernhardt https://www.destroyallsoftware.com/talks/boundaries ● Jay Fields on Working Effectively with Unit Tests - http://www.se-radio.net/2016/05/se-radio-episode-256-jay-fields-on-working-effectively-with-unit-test s/ ● XUnit Test Patterns - http://xunitpatterns.com/index.html ● Tautoloy Tests - https://medium.com/@rowillia/tautology-tests-7dabd81ade30