Download - How not to suck at unit tests
@benjamminstl
How Not to Suck at Unit TestsA presentation for Code PaLOUsa April 28, 2015
@benjamminstl
How I’ve Sucked at Unit TestsA presentation for Code PaLOUsa April 28, 2015
@benjamminstl
Ben BishopPurdue University graduate with a degree in Computer Graphics Technology. 10+ years of development experience. Rendr Co-Founder.
@benjamminstl
David Ortinau15+ years of development experience. Xamarin MVP. Beard Enthusiast. Rendr Co-Founder.
@benjamminstl
A little about RendrWe are a people focused software studio, building engaging solutions to solve real world problems and improve lives.
@benjamminstl
@benjamminstl
@benjamminstl
@benjamminstl
@benjamminstl
@benjamminstl
@benjamminstl
GoalsIf you take just one thing from this presentation, then I have achieved my goal.
@benjamminstl
2009
@benjamminstl
Typical Production Experience
Time
Productivity
@benjamminstl
Typical Production Experience
Time
Productivity
We can totally do that! We’re Rockstar Ninjas!
@benjamminstl
Typical Production Experience
Time
Productivity
Noooooo, the world will end! We hate our lives.
@benjamminstl
@benjamminstl
@benjamminstl
A Culture of NO
@benjamminstl
A Culture of Friction
@benjamminstl
NO
NO
NONO
NO
NO
NOT Possible
Can’tNOT within scope
NO
NO Time
@benjamminstl
Friction wastes energyFriction robs us of efficiency
@benjamminstl
@benjamminstl
Scrum
Ken Schwaber
@benjamminstl
@benjamminstl
@benjamminstl
Saying “yes” introduces risk.
@benjamminstl
The Land Scrum Forgothttps://www.youtube.com/watch?v=hG4LH6P8Syk
@benjamminstl
Segue
@benjamminstl
Six Projects with Unit Tests
@benjamminstl
Six “Failures”
@benjamminstl
Failed Attempt #1 at Unit Testing
@benjamminstl
@benjamminstl
Lessons Learned- Couldn’t automate testing through UI- Video streaming is extremely hard to test- Model/View architecture did not facilitate testing- Any testable state was in the view
@benjamminstl
Testable View State
@benjamminstl
Failed Attempt #2 at Unit Testing
@benjamminstl
@benjamminstl
Lessons Learned• Tests that test a server API aren’t Unit Tests• Hard to figure out how to not pollute your database with junk
data• Actually considered “integration test”• Best to separate server tests from app tests• Again, architecture didn’t support true unit tests
@benjamminstl
Separate Server Tests
@benjamminstl
Stay DRY
@benjamminstl
Stay DRY
@benjamminstl
Stay Performant
@benjamminstl
Failed Attempt #3 at Unit Testing
@benjamminstl
@benjamminstl
Lessons Learned• Hard to write tests for already existing classes• Couldn’t test private functions
• Spies• Have your TestCase extend the class you’re testing• Levels!
@benjamminstl
Jason Sonmezhttp://simpleprogrammer.com/2010/12/12/back-to-basics-why-unit-testing-is-hard/
Level 1 Unit Testing is where we have a single class with no external dependencies and no state. We are just testing an algorithm.
Level 2 Unit Testing is where we have a single class with no external dependencies but it does have state. We are setting up an object and testing it as a whole.
Level 3 Unit Testing is when we have a single class with at least one external dependency, but it does not depend on its own internal state.
Level 4 Unit Testing is when we have a single class with at least one external dependency and depends on its own internal state.
@benjamminstl
How do you test protected elements?
@benjamminstl
Test Spy
@benjamminstl
Test Spy
@benjamminstl
Failed Attempt #4 at Unit Testing
@benjamminstl
@benjamminstl
Lessons Learned• Use TestCase data meta tags• ViewModel architecture is very testable• Beware Yak Shaving
• testing setter/getters• constructor assignments!
!
@benjamminstl
Solution
@benjamminstl
Solution
@benjamminstl
Solution
@benjamminstl
Failed Attempt #5 at Unit Testing
@benjamminstl
@benjamminstl
Lessons Learned• Don’t use static/hard-singleton classes
• Static classes and/or extension methods cannot be replaced with Fake or Mock
• TestData brittleness• Use data fixtures like AutoFixture, otherwise you have to
constantly update your test data generators.• When testing integration test behavior not results• Beware of the Red, Green, Refactor blur
@benjamminstl
VMIC
View
CommandInputInvoker OutputInvoker
Mediator
@benjamminstl
@benjamminstl
Testing Results
@benjamminstl
Static Class
@benjamminstl
FakeItEasy
@benjamminstl
FakeItEasy
@benjamminstl
Homegrown Brittleness
@benjamminstl
AutoFixture
@benjamminstl
Failed Attempt #6 at Unit Testing
@benjamminstl
@benjamminstl
Lessons Learned• Set up brittleness
• Don’t use DI containers• Readability
• What is easy to write is not easy to read• Find ways to write less code
• Use interface tools/markup• Binding frameworks• Share code across platforms!
@benjamminstl
Improve Readability
@benjamminstl
Improve Readability
@benjamminstl
SolutionLess code
@benjamminstl
All of the Native, None of the IsolationThe best of both worlds: Code Portability and Tailored UIs
Number of Classes Percent (with Unit Tests) Percent (no Unit Tests)Core 207 43.2% 64.4%Tests 158 32.9%
Android 58* 12.2% 18.1%
iOS 56 11.7% 17.5%
Total 479 (321)
*includes .axml and .xml files
@benjamminstl
All of the Native, None of the IsolationThe best of both worlds: Code Portability and Tailored UIs
Number of Lines Percent (with Unit Tests) Percent (no Unit Tests)Core 9,886 35.3% 44.9%Tests 5,979 21.4%
Android 5,606* 20.0% 20.0%
iOS 6,512 23.3% 29.6%
Total 27,983 (22,004)
*includes .axml and .xml files
@benjamminstl
MVVM
View
ViewModel
(via bindings)
Service
@benjamminstl
Example
@benjamminstl
Closing Thoughts
@benjamminstl
Unit Testing is a habit that is no different than dieting or working out.
@benjamminstl
Small steps to a larger goal works better than trying to be perfect from the get go.
@benjamminstl
Small steps to a larger goal works better than trying to be perfect from the get go.
@benjamminstl
Test Code isn’t easyThe quality of your test code has to be equal to or greater than your production code. If test code is an after thought and isn’t refactored it too will become brittle.
@benjamminstl
Get used to failureA lot of devs want to avoid unit testing because seeing failed tests forces you to deal with the consequences of your change.
@benjamminstl
Ignorance is bliss…Until a client asks you to change something and you don’t know what’s going to break.
@benjamminstl
Research
@benjamminstl
Practice
@benjamminstl
Code Reviews
@benjamminstl
Thank You
David Ortinau 314.280.8445 [email protected]
Ben Bishop 314.775.8800 [email protected]