The GetCityWeatherByZip method returns the results of a zipcode query in the following structure:
In this application, the requirements for a valid CurrentConditions result will be the following required fields:
- Success
- City
- State
- Temperature
- Remarks
I setup a new solution and add a test project. In that project, I add a new class called CurrentConditionsTests and add my TestFixture attribute.
My first test will be to create my CurrentConditions class and setup the constructor to accept a string. Remember, a test that cannot compile constitutes as a failing test. Using the [Alt-Enter] keyboard shortcuts in Resharper, I quickly create my CurrentConditions class and get the constructor all setup.
With my code completed, I re-compile and run my test.
The next test would be to make sure my new class can get to my first required element; Success; In a new test, I make sure I only give the CurrentConditions constructor something, say "foo" and verify the property. When building this test, notice that I have not yet created the Success property. I again use Reshaper [Alt-Enter] to quickly create this property.
To make my test pass, I do the easiest thing:
Doing the easiest thing forces me to create another test to drive out getting the success element data, so I create another test and supply different data; "<WeatherResult><Success>false</Success></WeatherResult>".
When I run all my tests, my first tests fails because it's trying to load an empty string into an XmlDocument. The second test also fails because it's trying to load "foo" into an XmlDocument. To get these tests passing, I'll delete the first since its only purpose was to build some really basic infrastructure. Secondly, I'll update the second test with a valid Xml snippet to return true.
The next set of tests will focus on the validity of the field as well as the fields existence. In my example, if the WeatherResult does not have the Success node, my code needs to throw an Exception. My new test looks like:
When I run this test, it fails because my code did not throw an ApplicationException.
To make it pass, I need guard condition for my property:
The last validation step is to verify the Success property can convert the result to a bool, if not, set it to false. Here is the new test:
To pass:
Yuck, now I get to say one of my favorite phrases. With TDD it's OK to write crap, because you get to refactor. That's a lot of nasty stuff in the property getter. I like my properties nice and clear, it should return a private variable.
With a little refactoring, my code now looks a little better:
With that refactoring, I need to have the diligence to make sure my tests are still valid. My one test, ShouldThrowIfSuccessIsMissing, no longer needs to access the Success property to throw since I moved that code to the constructor.
I think this is a good place to stop for this post, it's getting a little long. The next post, I'll add tests for the second required field and get into some really fun refactoring. Comments are welcome!








