- You Can't Know Everything
- Raise Your Confidence
- Let's Discover Something
- Encode the Knowledge in Tests
- Go Where No Man Has Gone Before
- Conclusion
Encode the Knowledge in Tests
As previously mentioned, putting your newly found knowledge into tests is a great way to capture the knowledge you have gained. The tests not only document your findings for other developers to read, they also ensure the knowledge is still valid and not out-of-date. It is sometimes hard to write the tests when you do not know what you are testing, so spiking is often carried out without tests being written first. This is not always the case, as Ron Jeffries shows us in his book Extreme Programming Adventures in C# (Microsoft Press, 2004). In the book, Ron carries out spikes purely with tests.
It is not a hard-and-fast rule, and I personally find I can be more playful and creative if I can muck around with ideas in code without the concern of testing. I can write the tests after I understand the technology being researched.
Let's put our newly gained knowledge of how the time zones are stored into a test fixture. Notice that we are testing the helper methods that build the values out of the byte arrays. These helper methods will likely be extracted into a real class when we come to use the time zone information in our project. Having tests for them means that the refactoring exercise that will happen when we need those methods can be done with much more confidence.
using System; using Microsoft.Win32; using NUnit.Framework; [TestFixture] public class TimeZoneTests { [Test] public void TestRegistryKey() { RegistryKey regKey = Registry.LocalMachine; regKey = regKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVer- sion\Time Zones\"); Assert.IsNotNull(regKey, "Invalid registry key"); } [Test] public void TestMakeUShort() { ushort testVal = MakeUShort(0, 0); Assert.AreEqual(0,testVal); testVal = MakeUShort(1, 0); Assert.AreEqual(1,testVal); testVal = MakeUShort(byte.MaxValue, 0); Assert.AreEqual(byte.MaxValue,testVal); testVal = MakeUShort(0, 1); Assert.AreEqual(byte.MaxValue+1,testVal); testVal = MakeUShort(byte.MaxValue, byte.MaxValue); Assert.AreEqual(ushort.MaxValue,testVal); } [Test] public void TestMakeInt() { int testVal = MakeInt(0, 0); Assert.AreEqual(0,testVal); testVal = MakeInt(1, 0); Assert.AreEqual(1,testVal); testVal = MakeInt(ushort.MaxValue, 0); Assert.AreEqual(ushort.MaxValue,testVal); testVal = MakeInt(0, 1); Assert.AreEqual(ushort.MaxValue+1,testVal); testVal = MakeInt(ushort.MaxValue, ushort.MaxValue); Assert.AreEqual(-1,testVal); } [Test] public void TestGetValueFromBytes() { byte[] testBytes = {0,0,0,0,0,0,0,0}; int testVal = GetValueFromBytes(testBytes,0); Assert.AreEqual(0, testVal); testVal = GetValueFromBytes(testBytes,4); Assert.AreEqual(0, testVal); testBytes[0] = byte.MaxValue; testBytes[1] = byte.MaxValue; testVal = GetValueFromBytes(testBytes,0); Assert.AreEqual(ushort.MaxValue, testVal); testBytes[2] = byte.MaxValue; testBytes[3] = byte.MaxValue; testVal = GetValueFromBytes(testBytes,0); Assert.AreEqual(-1, testVal); testBytes[0] = 0; testBytes[1] = 0; testVal = GetValueFromBytes(testBytes,0); Assert.AreEqual(-1-ushort.MaxValue, testVal); } private ushort MakeUShort(byte low, byte high) { return (ushort) (low | (high<< 8)); } private int MakeInt(ushort low, ushort high) { return (int) (low | (high<< 16)); } private int GetValueFromBytes(byte[] data, int offset) { int nResult = 0; ushort lowWord = MakeUShort(data[offset],data[offset+1]); ushort highWord = MakeUShort(data[offset+2],data[offset+3]); nResult = MakeInt( lowWord, highWord ); return nResult; } [Test] public void TestTimeZoneInfoForGMT() { RegistryKey regKey = Registry.LocalMachine; regKey = regKey.OpenSubKey( @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\GMT Stan- dard Time"); Assert.IsNotNull(regKey, "Invalid registry key"); System.Byte[] tziData = (Byte[])regKey.GetValue("TZI"); int bias = GetValueFromBytes(tziData, 0); Assert.AreEqual(0, bias, "Bias was incorrect"); int standardBias = GetValueFromBytes(tziData, 4); Assert.AreEqual(0, standardBias, "Standard Bias was incorrect"); int daylightBias = GetValueFromBytes(tziData, 8); Assert.AreEqual(-60, daylightBias, "Daylight Bias was incorrect"); int month = MakeUShort(tziData[14],tziData[15]); Assert.AreEqual(10, month, "Month for change to standard time should be Oct"); DayOfWeek dayofWeek = (DayOfWeek) MakeUShort(tziData[16],tziData[17]); Assert.AreEqual(DayOfWeek.Sunday, dayofWeek, "Time should change on a Sun"); int day = MakeUShort(tziData[18],tziData[19]); Assert.AreEqual(5, day, "Time should change on 5th or last Sunday of month"); int hour = MakeUShort(tziData[20],tziData[21]); Assert.AreEqual(2, hour, "Time should change at 2am"); int minute= MakeUShort(tziData[22],tziData[23]); Assert.AreEqual(0, minute, "Time should change at 2am - zero minutes"); month = MakeUShort(tziData[30],tziData[31]); Assert.AreEqual(3, month, "Month for change to daylight savings should be Mar"); dayofWeek = (DayOfWeek) MakeUShort(tziData[32],tziData[33]); Assert.AreEqual(DayOfWeek.Sunday, dayofWeek, "Time should change to daylight on a Sun"); day = MakeUShort(tziData[34],tziData[35]); Assert.AreEqual(5, day, "Time should change on 5th or last Sunday of month"); hour = MakeUShort(tziData[36],tziData[37]); Assert.AreEqual(1, hour, "Time should change at 1am"); minute= MakeUShort(tziData[38],tziData[39]); Assert.AreEqual(0, minute, "Time should change at 1am - zero minutes"); } }