1 / 30

Un-Testable Code with Visual Studio 2012 Fakes

Learn how to test un-testable code using Visual Studio 2012 Fakes. Discover common indicators of un-testable code and explore effective unit testing techniques.

blodwyn
Download Presentation

Un-Testable Code with Visual Studio 2012 Fakes

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. DEV411 DEV411Testing Un-Testable Code with Visual Studio 2012 Fakes Peter Provost Sr. Program Manager Lead Microsoft Corporation

  2. Warning! • This is a 400 level deep dive on Visual Studio 2012 Fakes! • Assumptions • You are comfortable with .NET and Unit Testing • You already understand the basics of mocks, stubs, etc. • You believe that unit testing has significant benefits • And… • You want to see code and real problems • You want to have fun and are willingto ask questions !

  3. Effective unit testing is one of the biggestcontributors to high quality software. Testing legacy code is hard, and sometimes impossible. Or is it?

  4. What is un-testable code? Where do we find it? Common indicators Complex test setup and teardown Environmental dependencies Public static methods Hidden object creation Complex external frameworks No tests at all! • “Get ‘er done” code • Business logic in code-behind • Classes with too many dependencies • Database logic mixed with business logic • Testability was not a consideration • Or was explicitly avoided • Monolithic, highly-coupled designs Any system where the tests require complex setup or where the tests run very slowly is basically untestable

  5. A simple test setup example • The method we want to unit test boolIsFileEmpty(string file) { var content = File.ReadAllText(file); return content.Length == 0; } File.ReadAllText(file); This dependency forces… • Is this a “good” test? …this ugly setup code void FileExistsTest() { File.Write("foo.txt", ""); var result = IsFileEmpty("foo.txt") Assert.IsTrue(result); } File.Write("foo.txt", "");

  6. Environmental Dependencies • Consider the following Y2K code: public void ThrowIfEndOfTheWorld() { if (DateTime.Now == new DateTime(2000,1,1)) throw new Y2KBugException(); } • How would you test it reliably?

  7. Environmental Dependencies • How about this? Why is this bad? [DllImport("kernel32.dll")] extern static boolSetSystemTime(ref SystemTime time); [TestMethod] public void Y2KTest() { SetSystemTime(2000,1,1,0,0,0); Assert.Throws( () => ThrowIfEndOfTheWorld() ); }

  8. Isolation is critical • When you can’t isolate • Slow tests with complicated setup • Non-deterministic results • May be totally untestable • Two choices • Testable design • Abstraction layers, interfaces, dependency injection, stubs and overrides • Un-testable design • No abstraction layers, lots of static methods, sealed typed, etc.

  9. SOLID Principles Single Responsibility There should never be more than one reason for a class to change. S • Open/closed Principle • A module should be open for extension but closed for modification. O • Liskov Substitutability Principle • Subclasses should be substitutable for their base classes. L I • Interface Segregation Principle • Many client specific interfaces are better than one general purpose interface. D • Dependency Inversion Principle • Depend upon Abstractions. Do not depend upon concretions.

  10. Refactoring to Interfaces • Replace external calls with interfaces • Wrap external APIs • Interface exposes only what you consume • Class expresses requirements via interface dependencies • Useful patterns • Null Object • Default Implementation • Dependency Injection / Inversion of Control

  11. Refactoring to Interfaces Removing external dependencies byintroducing interface dependencies

  12. Review: Refactoring to Interfaces • The good parts • The code expresses its requirements • Very loosely coupled to external things • Free gift: Easier to replace external APIs later • Higher cohesion in you classes • When done right • But there are dangers • Dependency Addiction • Type explosion • Can be expensive and disruptive to the code

  13. Unit Testing with Interface Dependencies • Stubs and Mocks • Provide easy to use, concrete implementations for your testing • Similar but different in their approach • Visual Studio 2012 Stubs • Generated at compile time (runs fast) • Uses C# language features (no special API) • Type compatible (is-a) with the Interface

  14. Visual Studio 2012 Stubs Unit Testing code that has interface dependencies

  15. Review: Visual Studio 2012 Stubs • Concrete derivatives of interfaces and non-sealed classes • Generated at compile time • Run very fast • Uses standard language notations • No special API to learn • Delegates provide implementation • Constructor initializers to organizeyour delegate overrides Visual Studio StubS

  16. What about when you can’t refactor? • Framework Issues • If your class derives from an untestable, concrete typethat has complex internal setup • Or a complex graphs of objects must be setup properly before you can create and test your object • Expediency • Lots of legacy code and no time • Organizational design prohibitions

  17. The Catch-22 of Refactoring to Interfaces Refactoring defined: A disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior. —Martin Fowler, http://refactoring.com When code doesn’t have unit tests, how do you know if you changed the external behavior?

  18. Visual Studio 2012 Shims Isolating your code from external dependencies the brute force way

  19. Review: Visual Studio 2012 Shims • Runtime interception of any .NET method • Uses the profiler to detour calls • “Monkey patching” for .NET • Use it when you… • Have external components that cannot be refactored • SharePoint, ASP.NET, Office, etc. • Need to override non-virtual methods • Static methods, constructors, sealed types, properties • Have legacy code with untestable designs

  20. The Catch-22 Revisited • When you need to refactor to interfaces • First you must define the original behavior with unit tests • You can use Shims to provide the test coverage • But don’t stop there!! • Once you have the coverage • Do the refactoring • Add new tests using stubs to verify the behavior • Keep the original test running • When you’re done, you can remove the shims test

  21. Tips & Tricks • Configure the Fakes compiler to omit things you don’t use • Use closures to collect data from delegate methods • You can add missing System.* types via configuration • This can be dangerous! • Declare your ShimsContext within each test • Not doing this is dangerous! • Get rid of the Shims-based tests as soon as you can • Much slower to execute than Stubs • Depend on internal knowledge of your system

  22. Visual Studio 2012 FakesTips and Tricks Configuring, troubleshooting and how to not delete your hard drive

  23. SOLID Principles (redux) Single Responsibility There should never be more than one reason for a class to change. S • Open/closed Principle • A module should be open for extension but closed for modification. O • Liskov Substitutability Principle • Subclasses should be substitutable for their base classes. L I • Interface Segregation Principle • Many client specific interfaces are better than one general purpose interface. D • Dependency Inversion Principle • Depend upon Abstractions. Do not depend upon concretions.

  24. Effective unit testing is one of the biggestcontributors to high quality software. Testing legacy code is hard, but not impossible. Then you can use the tests to improve your design.

  25. Thank you! Have questions now? • Please use the mics • I will stick around outside after Think of a question later? peter.provost@microsoft.com www.peterprovost.org @pprovost Peter Provost Find Me Later At DEV01-TLC: Application Lifecycle Management (ALM)

  26. Related Content • Breakout Sessions • DEV214 Introducing the New Visual Studio 11 Unit Testing Experience • AAP401 Real World Developer Testing with Visual Studio 2012 • DEV411 Testing Un-testable Code with Fakes in Visual Studio 2012 • AAP330 Compile & Execute Requirements in .NET • Hands on Labs • DEV17-HOL Explore the New Unit Testing and Code Clone Capabilities of Visual Studio 2012 • Product Demo Stations • DEV01-TLCApplication Lifecycle Management (ALM)

  27. Resources Learning TechNet • Connect. Share. Discuss. • Microsoft Certification & Training Resources http://europe.msteched.com www.microsoft.com/learning • Resources for IT Professionals • Resources for Developers • http://microsoft.com/technet http://microsoft.com/msdn

  28. Evaluations Submit your evals online http://europe.msteched.com/sessions

  29. © 2012 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.

More Related