MSDN Magazine - December 2008 - (Page 38) Figure 1 Workflow Code public void ProcessWorkflowEvent( string newStatus, long workflowId) { // First, go get the XML out of the database OracleConnection connection = new OracleConnection(ProjectConfiguration.ConnectionString); OracleCommand command = connection.CreateCommand(); command.CommandType = CommandType.StoredProcedure; command.CommandText = "sp_that_returns_the_workflow_information"; // and set the necessary parameters command.ExecuteNonQuery(); string xml = (string) command.Parameters["@xml"].Value; XmlDocument document = new XmlDocument(); document.LoadXml(xml); // // // // depending upon what the new status is, make changes to the Xml document, decide whether or not to send an email, then save the changed Xml document with another set of ADO.NET calls } Fast The automated tests should run quickly. Again, the goal is to make the overall development process faster by establishing rapid feedback cycles to find problems. Slow-running tests will retard productivity. These four points are directly related to design decisions, specifically to being mindful in regard to the classic design qualities of separation of concerns, cohesion, and coupling—things that you generally want anyway. That said, there are certain design patterns, such as inversion of control and the various forms of separated presentation, that can greatly enhance testability. Testability is about creating rapid, effective feedback cycles to find problems in your code. As in all things, there are some trade-offs. Many of these patterns are controversial because they don’t quite fit the current direction of Microsoft tooling, are relatively new, or seem to negate the usefulness of some traditional .NET approaches. I’d like to use the rest of this column to present some sample scenarios and design patterns, and try to explain why these patterns are considered so important by teams that value TDD and automated testing. Isolate the Ugly Stuff Five years ago I considered myself to be strong in object-oriented design. Then I worked on a couple of projects that used TDD and learned firsthand just how little I really knew. Before going into these projects, I had read quite a bit about writing unit tests with NUnit that showed examples like this: [TestFixture] public class HolyHandGrenadeTester { [Test] public void users_should_count_to_three_after_pulling_the_pin() { new HolyHandGrenade().TheNumberToCountTo().ShouldEqual(3); } } Armed with these examples, I went into my first TDD project and immediately ran into trouble. My C# code was interacting with databases, Web services, the ASP.NET runtime, and external systems. Those things were a lot harder to test than code that runs completely inside a single CLR AppDomain. I specifically remember having a lot of trouble writing unit tests for a little custom workflow subsystem. The workflow data was fairly complex and hierarchical, so I decided at the time to store the state of the workflow as XML data in an Oracle CLOB field. The workflow code itself knew to pull out the XML data from the database, work on it, update the XML, then invoke more ADO.NET code to save the changes back to the database. My code looked like the contrived example shown in Figure 1. Let’s think about what you would have to do to write automated unit tests for this code. The only way to feed the test input into this data was to create a properly formed XML document and then put that XML into a database row. There was a lot of business logic that would change the state of the XML file, and therefore a lot of permutations of previous state and user input that I had to test. As I said before, I struggled mightily when I tried to write unit tests for this code. My real issue was getting the business rules about the workflow state changes correct. The need to set up the XML data in the database was slowing me down. This is when I learned my first important lesson about testability: some things are just plain ugly to deal with in testing. What I needed to do was isolate the ugly stuff. All I really mean by “ugly stuff ” is any kind of code or infrastructure that is complicated or laborious or just plain inconvenient to get into a test harness, or that makes tests run very slowly. My partial list of ugly stuff would be: • Database access. As most TDD practitioners will tell you, tests that involve a database will run an order of magnitude slower than tests that can run completely within a single CLR AppDomain. Setting up data in a database is much more time intensive than simply building objects in memory because of referential integrity and data constraints. When you test against the database, you will often find yourself adding setup data that has nothing to do with the actual test to the database just to satisfy referential integrity and value constraints. • GUI technologies, such as Windows Presentation Foundation (WPF) or testing Web apps directly in the browser. It is possible to test the user interface itself, but it’s a significant investment in time and the tests run even slower than database tests. • Active Directory access. • Web services. It’s hard enough to set up a known state for testing your own code. Coordinating with a completely separate team to set up tests across two or more systems is more difficult. My advice is to make sure that the functionality of your Web services can be tested independent of the actual Web service protocols. For Web services external to your code, I strongly advise having your code depend on an abstracted interface for external Web services rather than use a Web service proxy class directly. This will enable you to replace the external Web service with your own stubbed implementation during internal testing. • Configuration files. Patterns in Practice 38 msdn magazine
Table of Contents Feed for the Digital Edition of MSDN Magazine - December 2008 MSDN Magazine - December 2008 Contents Toolbox CLR Inside Out Advanced Basics Cutting Edge Patterns In Practice Team System Real-World WF Visual Studio OBA Tools SOA Data Access Geneva Framework Test Run Foundations Windows With C++ Going Places End Bracket MSDN Magazine - December 2008 MSDN Magazine - December 2008 - (Page Intro) MSDN Magazine - December 2008 - Contents (Page Cover1) MSDN Magazine - December 2008 - Contents (Page Cover2) MSDN Magazine - December 2008 - Contents (Page 1) MSDN Magazine - December 2008 - Contents (Page 2) MSDN Magazine - December 2008 - Contents (Page 3) MSDN Magazine - December 2008 - Contents (Page 4) MSDN Magazine - December 2008 - Contents (Page 5) MSDN Magazine - December 2008 - Contents (Page 6) MSDN Magazine - December 2008 - Contents (Page 7) MSDN Magazine - December 2008 - Contents (Page 8) MSDN Magazine - December 2008 - Contents (Page 9) MSDN Magazine - December 2008 - Contents (Page 10) MSDN Magazine - December 2008 - Toolbox (Page 11) MSDN Magazine - December 2008 - Toolbox (Page 12) MSDN Magazine - December 2008 - Toolbox (Page 13) MSDN Magazine - December 2008 - Toolbox (Page 14) MSDN Magazine - December 2008 - CLR Inside Out (Page 15) MSDN Magazine - December 2008 - CLR Inside Out (Page 16) MSDN Magazine - December 2008 - CLR Inside Out (Page 17) MSDN Magazine - December 2008 - CLR Inside Out (Page 18) MSDN Magazine - December 2008 - CLR Inside Out (Page 19) MSDN Magazine - December 2008 - CLR Inside Out (Page 20) MSDN Magazine - December 2008 - CLR Inside Out (Page 21) MSDN Magazine - December 2008 - Advanced Basics (Page 22) MSDN Magazine - December 2008 - Advanced Basics (Page 23) MSDN Magazine - December 2008 - Advanced Basics (Page 24) MSDN Magazine - December 2008 - Advanced Basics (Page 25) MSDN Magazine - December 2008 - Advanced Basics (Page 26) MSDN Magazine - December 2008 - Advanced Basics (Page 27) MSDN Magazine - December 2008 - Advanced Basics (Page 28) MSDN Magazine - December 2008 - Cutting Edge (Page 29) MSDN Magazine - December 2008 - Cutting Edge (Page 30) MSDN Magazine - December 2008 - Cutting Edge (Page 31) MSDN Magazine - December 2008 - Cutting Edge (Page 32) MSDN Magazine - December 2008 - Cutting Edge (Page 33) MSDN Magazine - December 2008 - Cutting Edge (Page 34) MSDN Magazine - December 2008 - Cutting Edge (Page 35) MSDN Magazine - December 2008 - Cutting Edge (Page 36) MSDN Magazine - December 2008 - Patterns In Practice (Page 37) MSDN Magazine - December 2008 - Patterns In Practice (Page 38) MSDN Magazine - December 2008 - Patterns In Practice (Page 39) MSDN Magazine - December 2008 - Patterns In Practice (Page 40) MSDN Magazine - December 2008 - Patterns In Practice (Page 41) MSDN Magazine - December 2008 - Patterns In Practice (Page 42) MSDN Magazine - December 2008 - Patterns In Practice (Page 43) MSDN Magazine - December 2008 - Team System (Page 44) MSDN Magazine - December 2008 - Team System (Page 45) MSDN Magazine - December 2008 - Team System (Page 46) MSDN Magazine - December 2008 - Team System (Page 47) MSDN Magazine - December 2008 - Team System (Page 48) MSDN Magazine - December 2008 - Team System (Page 49) MSDN Magazine - December 2008 - Team System (Page 50) MSDN Magazine - December 2008 - Team System (Page 51) MSDN Magazine - December 2008 - Real-World WF (Page 52) MSDN Magazine - December 2008 - Real-World WF (Page 53) MSDN Magazine - December 2008 - Real-World WF (Page 54) MSDN Magazine - December 2008 - Real-World WF (Page 55) MSDN Magazine - December 2008 - Real-World WF (Page 56) MSDN Magazine - December 2008 - Real-World WF (Page 57) MSDN Magazine - December 2008 - Real-World WF (Page 58) MSDN Magazine - December 2008 - Real-World WF (Page 59) MSDN Magazine - December 2008 - Real-World WF (Page 60) MSDN Magazine - December 2008 - Real-World WF (Page 61) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 62) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 63) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 64) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 65) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 66) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 67) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 68) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 69) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 70) MSDN Magazine - December 2008 - Visual Studio OBA Tools (Page 71) MSDN Magazine - December 2008 - SOA Data Access (Page 72) MSDN Magazine - December 2008 - SOA Data Access (Page 73) MSDN Magazine - December 2008 - SOA Data Access (Page 74) MSDN Magazine - December 2008 - SOA Data Access (Page 75) MSDN Magazine - December 2008 - SOA Data Access (Page 76) MSDN Magazine - December 2008 - SOA Data Access (Page 77) MSDN Magazine - December 2008 - SOA Data Access (Page 78) MSDN Magazine - December 2008 - SOA Data Access (Page 79) MSDN Magazine - December 2008 - SOA Data Access (Page 80) MSDN Magazine - December 2008 - SOA Data Access (Page 81) MSDN Magazine - December 2008 - Geneva Framework (Page 82) MSDN Magazine - December 2008 - Geneva Framework (Page 83) MSDN Magazine - December 2008 - Geneva Framework (Page 84) MSDN Magazine - December 2008 - Geneva Framework (Page 85) MSDN Magazine - December 2008 - Geneva Framework (Page 86) MSDN Magazine - December 2008 - Geneva Framework (Page 87) MSDN Magazine - December 2008 - Geneva Framework (Page 88) MSDN Magazine - December 2008 - Geneva Framework (Page 89) MSDN Magazine - December 2008 - Geneva Framework (Page 90) MSDN Magazine - December 2008 - Test Run (Page 91) MSDN Magazine - December 2008 - Test Run (Page 92) MSDN Magazine - December 2008 - Test Run (Page 93) MSDN Magazine - December 2008 - Test Run (Page 94) MSDN Magazine - December 2008 - Test Run (Page 95) MSDN Magazine - December 2008 - Test Run (Page 96) MSDN Magazine - December 2008 - Test Run (Page 97) MSDN Magazine - December 2008 - Test Run (Page 98) MSDN Magazine - December 2008 - Test Run (Page 99) MSDN Magazine - December 2008 - Test Run (Page 100) MSDN Magazine - December 2008 - Foundations (Page 101) MSDN Magazine - December 2008 - Foundations (Page 102) MSDN Magazine - December 2008 - Foundations (Page 103) MSDN Magazine - December 2008 - Foundations (Page 104) MSDN Magazine - December 2008 - Foundations (Page 105) MSDN Magazine - December 2008 - Foundations (Page 106) MSDN Magazine - December 2008 - Foundations (Page 107) MSDN Magazine - December 2008 - Foundations (Page 108) MSDN Magazine - December 2008 - Windows With C++ (Page 109) MSDN Magazine - December 2008 - Windows With C++ (Page 110) MSDN Magazine - December 2008 - Windows With C++ (Page 111) MSDN Magazine - December 2008 - Windows With C++ (Page 112) MSDN Magazine - December 2008 - Going Places (Page 113) MSDN Magazine - December 2008 - Going Places (Page 114) MSDN Magazine - December 2008 - Going Places (Page 115) MSDN Magazine - December 2008 - Going Places (Page 116) MSDN Magazine - December 2008 - Going Places (Page 117) MSDN Magazine - December 2008 - Going Places (Page 118) MSDN Magazine - December 2008 - Going Places (Page 119) MSDN Magazine - December 2008 - End Bracket (Page 120) MSDN Magazine - December 2008 - End Bracket (Page Cover3) MSDN Magazine - December 2008 - End Bracket (Page Cover4)
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.