Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Building Unit Tests correctly with VS 2013
About.ME
• Senior Consultant @CodeValue
• Developing software (Professionally) since 2002
• Mocking code since 2008
• Test...
/*
* You may think you know what the following code does.
* But you dont. Trust me.
* Fiddle with it, and youll spend many...
//This code sucks, you know it and I know it.
//Move on and call me an idiot later.
http://stackoverflow.com/questions/184...
“If we’re afraid to change
the very thing we’ve
created,
we failed as professionals”
Robert C. Martin
Legacy code
“Code without tests is bad code...
With tests, we can change the
behavior of our code quickly and
verifiably...”
Michael F...
This is a unit test
[Test]
public void CheckPassword_ValidUser_ReturnTrue()
{
bool result = CheckPassword(“user”, “pass”);...
This is also a unit test
[TestMethod]
public void CheckPassword_ValidUser_ReturnTrue()
{
bool result = CheckPassword(“user...
A unit test is…
1. Tests specific functionality
2. Clear pass/fail criteria
3. Good unit test runs in isolation
Unit testing is an iterative effort
Unit testing is an iterative effort
There’s more to unit tests then just “tests”
Written by the developer who wrote the code
Quick feedback
Avoid stupid bug...
13
copyright 2008 trainologic LTD
13
One last reason
You’re already Testing your code – manually
So why not save the time?
The cost of unit testing
120%
135%
115%
125%
0%
20%
40%
60%
80%
100%
120%
140%
IBM: Drivers MS: Windows MS: MSN MS: VS
Tim...
The value of unit testing
61%
38%
24%
9%
0%
20%
40%
60%
80%
100%
120%
140%
IBM: Drivers MS: Windows MS: MSN MS: VS
Using T...
The cost of bugs
0
1
2
3
4
5
6
7
8
9
10
0%
20%
40%
60%
80%
100%
Thousand$s
%defectscreated
Where does it hurt?
% of Defect...
Supporting environment
• The team
• Development environment
The Team
• The team commitment is important
• Learn from test reviews
• Track results
Tools of the trade
Server Dev Machine
Source
Control
Build Server
Test Runner
Code
CoverageBuild Script
Unit Testing
Frame...
Development environment
• Make it easy to write and run tests
– Unit test framework
– Test Runner
– Isolation framework
• ...
Unit testing frameworks
• Create test fixtures
• Assert results
• Additional utilities
• Usually provide command-line/GUI ...
[Test]
public void AddTest()
{
var cut = new Calculator();
var result = cut.Add(2, 3);
Assert.AreEqual(5, result);
}
This ...
Real code has dependencies
Unit test
Code under test
Dependency Dependency
The solution - Mocking
Fake object(s)
Unit test
Code under test
Dependency
Isolation
• Replace production logic with custom logic
• We do this in order to
– Focus the test on one class only
– Test ...
What Mocking framework can do for you?
• Create Fake objects
• Set behavior on fake objects
• Verify method was called
• A...
[Test]
public void IsLoginOK_LoggerThrowsException_CallsWebService()
{
var fakeLogger = Isolate.Fake.Instance<ILogger>();
...
Open source
• FakeItEasy
• Moq
• NMock3
• nSubtitute
• Rhino
Mocks
Free
• MS Fakes
Commercial
• Isolator
• JustMock
Moq
45%
Rhino Mocks
23%
None
9%
FakeItEasy
6%
Nsubstitute
6%
Isolator
4%
Moles
2%
MS Fakes
2%
JustMocks
2%
Other
1%
http:/...
Code Coverage
So, What is a good code coverage?
Source Control
Build Server
Commit
There you go
What’s new?
Build Agents
We automatically get
•Error reports & logs
•New v...
Build run at a Glance
How I failed unit testing my code
Unit testing is great!
Everything should be tested
I can test “almost” everything
Tests ...
A good unit test should be:
• Easy to understand
• Trustworthy
• Robust
Trust Your Tests!
Trustworthy means deterministic
Problem
• I cannot re-run the exact same test if a test fails
Solution
• Don’t use Random ...
Trustworthy also means not fragile
Ideally
A test would only fail if a bug was introduced
OR
Requirements changed
How to avoid fragile tests
• Don’t test private/internal (most of the time)
• Fake as little as necessary
• Test only one ...
Readable unit tests
Unit test intent should be clear!
1.What is being tested?
2.What is the desired outcome?
3.Why did tes...
Learn to write “clean tests”
[Test]
public void CalculatorSimpleTest()
{
calc.ValidOperation = Calculator.Operation.Multip...
Or suffer the consequences!
[Test]
public void CalculatorSimpleTest()
{
var calc = new Calculator();
calc.ValidOperation =...
Writing a good unit test
[Test]
public void
Multiply_PassTwoPositiveNumbers_ReturnCorrectResult()
{
var calculator = Creat...
So what about code reuse
Readability is more important than code reuse
• Create objects using factories
• Put common and o...
Avoid logic in the test (if, switch etc.)
Problem
• Test is not readable
• Has several possible paths
• High maintain cost
Tests should be deterministic
Solution
• Split test to several tests – one for each
path
– If logic change it’s easier to ...
How to start with unit tests
1. Test what you’re working on – right now!
2. Write tests to reproduce reported bug
3. When ...
Building unit tests correctly with visual studio 2013
Upcoming SlideShare
Loading in …5
×

Building unit tests correctly with visual studio 2013

2,633 views

Published on

Unit testing is now considered a mainstream practice, but that does not mean it is as common, pervasive or as well understood as it could or should be. Many programmers struggle with the quality of their tests and with the focus of their code. In this session we’ll learn how to write good unit testing code.

Published in: Software, Technology, Education
  • Be the first to comment

Building unit tests correctly with visual studio 2013

  1. 1. Building Unit Tests correctly with VS 2013
  2. 2. About.ME • Senior Consultant @CodeValue • Developing software (Professionally) since 2002 • Mocking code since 2008 • Test driven professional • Blogger: http://blog.drorhelper.com
  3. 3. /* * You may think you know what the following code does. * But you dont. Trust me. * Fiddle with it, and youll spend many a sleepless * night cursing the moment you thought youd be clever * enough to "optimize" the code below. * Now close this file and go play with something else. */ // // Dear maintainer: // // Once you are done trying to 'optimize' this routine, // and have realized what a terrible mistake that was, // please increment the following counter as a warning // to the next guy: // // total_hours_wasted_here = 42 //
  4. 4. //This code sucks, you know it and I know it. //Move on and call me an idiot later. http://stackoverflow.com/questions/184618/what-is-the- best-comment-in-source-code-you-have-ever-encountered We fear our code! //Abandon all hope ye who enter beyond this point //When I wrote this, only God and I understood what I was doing //Now, God only knows // I dedicate all this code, all my work, to my wife, Darlene, who will // have to support me and our three children and the dog once it gets // released into the public. //The following 1056 lines of code in this next method //is a line by line port from VB.NET to C#. //I ported this code but did not write the original code. //It remains to me a mystery as to what //the business logic is trying to accomplish here other than to serve as //some sort of a compensation shell game invented by a den of thieves. //Oh well, everyone wants this stuff to work the same as before. //I guess the devil you know is better than the devil you don't.
  5. 5. “If we’re afraid to change the very thing we’ve created, we failed as professionals” Robert C. Martin
  6. 6. Legacy code
  7. 7. “Code without tests is bad code... With tests, we can change the behavior of our code quickly and verifiably...” Michael Feathers - “Working effectively with legacy code”
  8. 8. This is a unit test [Test] public void CheckPassword_ValidUser_ReturnTrue() { bool result = CheckPassword(“user”, “pass”); Assert.That(result, Is.True); } D
  9. 9. This is also a unit test [TestMethod] public void CheckPassword_ValidUser_ReturnTrue() { bool result = CheckPassword(“user”, “pass”); Assert.IsTrue(result); } D
  10. 10. A unit test is… 1. Tests specific functionality 2. Clear pass/fail criteria 3. Good unit test runs in isolation
  11. 11. Unit testing is an iterative effort Unit testing is an iterative effort
  12. 12. There’s more to unit tests then just “tests” Written by the developer who wrote the code Quick feedback Avoid stupid bugs Immune to regression Change your code without fear In code documentation
  13. 13. 13 copyright 2008 trainologic LTD 13 One last reason You’re already Testing your code – manually So why not save the time?
  14. 14. The cost of unit testing 120% 135% 115% 125% 0% 20% 40% 60% 80% 100% 120% 140% IBM: Drivers MS: Windows MS: MSN MS: VS Time taken to code a feature WithoutTDD Using TDD
  15. 15. The value of unit testing 61% 38% 24% 9% 0% 20% 40% 60% 80% 100% 120% 140% IBM: Drivers MS: Windows MS: MSN MS: VS Using Test Driven Design Time To Code Feature Defect density of team Major quality improvement for minor time investment
  16. 16. The cost of bugs 0 1 2 3 4 5 6 7 8 9 10 0% 20% 40% 60% 80% 100% Thousand$s %defectscreated Where does it hurt? % of Defects Introduced Cost to Fix a Defect The pain is here! This is too late…
  17. 17. Supporting environment • The team • Development environment
  18. 18. The Team • The team commitment is important • Learn from test reviews • Track results
  19. 19. Tools of the trade Server Dev Machine Source Control Build Server Test Runner Code CoverageBuild Script Unit Testing Framework Isolation Framework
  20. 20. Development environment • Make it easy to write and run tests – Unit test framework – Test Runner – Isolation framework • Know where you stand – Code coverage
  21. 21. Unit testing frameworks • Create test fixtures • Assert results • Additional utilities • Usually provide command-line/GUI runner http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks
  22. 22. [Test] public void AddTest() { var cut = new Calculator(); var result = cut.Add(2, 3); Assert.AreEqual(5, result); } This is not a real unit test
  23. 23. Real code has dependencies Unit test Code under test Dependency Dependency
  24. 24. The solution - Mocking Fake object(s) Unit test Code under test Dependency
  25. 25. Isolation • Replace production logic with custom logic • We do this in order to – Focus the test on one class only – Test Interaction – Simplify Unit test writing
  26. 26. What Mocking framework can do for you? • Create Fake objects • Set behavior on fake objects • Verify method was called • And more...
  27. 27. [Test] public void IsLoginOK_LoggerThrowsException_CallsWebService() { var fakeLogger = Isolate.Fake.Instance<ILogger>(); Isolate .WhenCalled(() => fakeLogger.Write("")) .WillThrow(new LoggerException()); var fakeWebService = Isolate.Fake.Instance<IWebService>(); var lm = new LoginManagerWithMockAndStub(fakeLogger,fakeWebService); lm.IsLoginOK("", ""); Isolate.Verify.WasCalledWithAnyArguments(() => fakeWebService.Write("")); }
  28. 28. Open source • FakeItEasy • Moq • NMock3 • nSubtitute • Rhino Mocks Free • MS Fakes Commercial • Isolator • JustMock
  29. 29. Moq 45% Rhino Mocks 23% None 9% FakeItEasy 6% Nsubstitute 6% Isolator 4% Moles 2% MS Fakes 2% JustMocks 2% Other 1% http://osherove.com/blog/2012/5/4/annual-poll-which-isolation-framework-do- you-use-if-any.html
  30. 30. Code Coverage So, What is a good code coverage?
  31. 31. Source Control Build Server Commit There you go What’s new? Build Agents We automatically get •Error reports & logs •New version installer •Help files •More…
  32. 32. Build run at a Glance
  33. 33. How I failed unit testing my code Unit testing is great! Everything should be tested I can test “almost” everything Tests break all the time Unit testing is a waste of time 
  34. 34. A good unit test should be: • Easy to understand • Trustworthy • Robust Trust Your Tests!
  35. 35. Trustworthy means deterministic Problem • I cannot re-run the exact same test if a test fails Solution • Don’t use Random in tests – If you care about the values set them – If you don’t care about the values put defaults – Do not use Sleep & time related logic – fake it • Use fake objects to “force” determinism into the test • When possible avoid threading in tests.
  36. 36. Trustworthy also means not fragile Ideally A test would only fail if a bug was introduced OR Requirements changed
  37. 37. How to avoid fragile tests • Don’t test private/internal (most of the time) • Fake as little as necessary • Test only one thing (most of the time)
  38. 38. Readable unit tests Unit test intent should be clear! 1.What is being tested? 2.What is the desired outcome? 3.Why did test fail?
  39. 39. Learn to write “clean tests” [Test] public void CalculatorSimpleTest() { calc.ValidOperation = Calculator.Operation.Multiply; calc.ValidType = typeof (int); result = calc.Multiply(1, 3); Assert.IsTrue(result == 3); if (calc.ValidOperation == Calculator.Operation.Invalid) { throw new Exception("Operation should be valid"); } }
  40. 40. Or suffer the consequences! [Test] public void CalculatorSimpleTest() { var calc = new Calculator(); calc.ValidOperation = Calculator.Operation.Multiply; calc.ValidType = typeof (int); var result = calc.Multiply(-1, 3); Assert.AreEqual(result, -3); calc.ValidOperation = Calculator.Operation.Multiply; calc.ValidType = typeof (int); result = calc.Multiply(1, 3); Assert.IsTrue(result == 3); if (calc.ValidOperation == Calculator.Operation.Invalid) { throw new Exception("Operation should be valid"); } calc.ValidOperation = Calculator.Operation.Multiply; calc.ValidType = typeof (int); result = calc.Multiply(10, 3); Assert.AreEqual(result, 30); }
  41. 41. Writing a good unit test [Test] public void Multiply_PassTwoPositiveNumbers_ReturnCorrectResult() { var calculator = CreateMultiplyCalculator(); var result = calculator.Multiply(1, 3); Assert.AreEqual(result, 3); }
  42. 42. So what about code reuse Readability is more important than code reuse • Create objects using factories • Put common and operations in helper methods • Use inheritance – sparsely
  43. 43. Avoid logic in the test (if, switch etc.) Problem • Test is not readable • Has several possible paths • High maintain cost
  44. 44. Tests should be deterministic Solution • Split test to several tests – one for each path – If logic change it’s easier to update some of the tests (or delete them) • One Assert per test rule
  45. 45. How to start with unit tests 1. Test what you’re working on – right now! 2. Write tests to reproduce reported bug 3. When refactoring existing code – use unit tests to make sure it still works. 4. Delete obsolete tests (and code) 5. All tests must run as part of CI build

×