Unit Testing Good Practices Roy Osherove Chief Architect Typemock DEV204
Real World Agenda Making your tests trustworthy Creating maintainable tests Readable tests – last but not least! Team Agile - All rights reserved
Make Your tests trust worthy Test the right thing Removing or changing tests Assuring code coverage Avoid test logic Make it easy to run Team Agile - All rights reserved
Test the right thing [Test] Public void Sum() { int result = calculator.Sum(1,2); Assert.AreEqual(4,result, “bad sum”); } Team Agile - All rights reserved
Removing/Changing tests As rule – don’t change or remove. Always add new tests. Unless: It’s for clarity (functionality stays the same) Test is not needed Test is needed to run differently Team Agile - All rights reserved
Assuring code coverage [DEMO] Change production code and see what happens Make params into consts Remove “if” checks – or make into consts If all tests pass - something is missing or something is not needed Team Agile - All rights reserved
Avoid Test Logic No Ifs, SWITCH’s or CASE’s Only Create, configure, act and ASSERT Test logic == test bugs Fail first assures your test is correct as well! Team Agile - All rights reserved
Make it easy to run Integration vs. Unit tests Configuration vs. “ClickOnce” Laziness is key If some tests fail all the time no one listens One package *always* has to work! Team Agile - All rights reserved
Creating maintainable tests Avoid testing private/protected members Re-use test code (Create, Manipulate, Assert) Enforce test isolation Avoid Multiple Asserts Team Agile - All rights reserved
Test only publics Testing a private makes your test more brittle Makes you think about the design and usability of a feature Test-First leads to private members after Refactoring, but they are all tested! But sometimes there’s not choice Team Agile - All rights reserved
Reuse test code [DEMO] Create objects using common methods (factories) [make_XX] Manipulate and configure initial state using common methods [init_XX] Run common tests in common methods [verify_XX] Team Agile - All rights reserved
Enforce test isolation No dependency between tests! Don’t run a test from another test! Run alone or all together in any order Otherwise – leads to nasty “what was that?” bugs Team Agile - All rights reserved
Avoid Multiple Asserts Like having multiple tests But the first the fails – kills the others You won’t get the big picture (some symptoms) Hard to name Can lead to more debugging work Team Agile - All rights reserved
Creating readable tests Naming a unit test Naming variables Separate Assert from action Team Agile - All rights reserved
Naming a unit test Method name State under test Expected behavior/return value Add_LessThanZero_ThrowsException() Another angle: Add_LessThanZero_ThrowsException2() Team Agile - All rights reserved
No Magic Values Assert.AreEqual(1003, calc.Parse(“-1”)); Int parseResult = calc.Parse(NEGATIVE_ILLEGAL_NUMBER); Assert.AreEqual( NEGATIVE_PARSE_RETURN_CODE, parseResult)
Separate Assert from Action Previous example Assert is less cluttered More readable Allows handling the return value if needed It’s all about reability Team Agile - All rights reserved
Summary
Make Your tests trust worthy Test the right thing Removing or changing tests Assuring code coverage Avoid test logic Make it easy to run Team Agile - All rights reserved
Creating maintainable tests Avoid testing private/protected members Re-use test code (Create, Manipulate, Assert) Enforce test isolation Avoid Multiple Asserts Team Agile - All rights reserved
Creating readable tests Naming a unit test Naming variables Separate Assert from action Team Agile - All rights reserved
Maintainable Trustworthy Readable Team Agile - All rights reserved
question & answer
Resources www.Typemock.com www.ArtOfUnitTesting.com Typemock Isolator, IntelliTest www.ArtOfUnitTesting.com Free Chapters
Complete an evaluation on CommNet and enter to win an Xbox 360 Elite!
Required Slide © 2009 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries. The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.