InterviewSolution
| 1. |
What Are Some Of The Common Pitfalls Of Tdd/unit Testing? |
|
Answer» Some of the pitfalls I have discovered over the years are listed below along with some suggestions for avoiding or overcoming them: Brittle tests – It is easy to create tests that break when later functionality is added. Newer versions of mocking frameworks have helped with this PROBLEM by introducing mock types that demand that stated expectations are met on mocked dependencies, but don’t fail when additional interactions with those dependencies occur. As an example, in Rhino Mocks, you should use a DynamicMock object when it makes sense, rather than a StrictMock because the tests created with a DynamicMock are less brittle. Missed features – I highly recommend creating a specific test for each feature, even if the test is an exact duplicate of another test. The reason for this is that, in the FUTURE, those features MAY evolve independently, and it is likely that the one test shared by both will be modified to fit the first feature that changes, leaving the second untested. DateTimes don’t validate well – When comparing DateTime types, it is often difficult to get accurate results due to the rapid change in the current time and the varying degrees of precision of different time types. I have found it best to use a tolerance wherever possible in my DateTime testing. For example, I have created a custom Constraint for Rhino Mocks called a DateTimeConstraint that allows me to specify the tolerance that I will allow in my tests. That tolerance could be to the millisecond, the second, the minute, or whatever makes sense for that test. TYPE specific values don’t compare well – An Int32 with a value of 12345 is not the same as an Int64 with the same value. Be careful when comparing data types, even if the value in those types should be the same. It is often best to cast or convert the value with the lesser precision, to the other type. Testing using shared resources is difficult – While there is much discussion about what you call a test that TOUCHES the database, or another external resource such as a message queue, there is no doubt that interactions with those types of resources must still be tested. If the database or queue you are using is shared, it is possible that data can be manipulated during your tests, making these tests imprecise at best. Whenever possible, you should isolate these tests by using local resources if possible, or by creating the resources specifically for the test. That is, if in your test you create a message queue using a GUID defined in your test as the name of the queue, then use that for your tests and destroy the queue at the end of the test, you can be reasonably confident that no other user will be manipulating the data in that queue during the test. Some of the pitfalls I have discovered over the years are listed below along with some suggestions for avoiding or overcoming them: Brittle tests – It is easy to create tests that break when later functionality is added. Newer versions of mocking frameworks have helped with this problem by introducing mock types that demand that stated expectations are met on mocked dependencies, but don’t fail when additional interactions with those dependencies occur. As an example, in Rhino Mocks, you should use a DynamicMock object when it makes sense, rather than a StrictMock because the tests created with a DynamicMock are less brittle. Missed features – I highly recommend creating a specific test for each feature, even if the test is an exact duplicate of another test. The reason for this is that, in the future, those features may evolve independently, and it is likely that the one test shared by both will be modified to fit the first feature that changes, leaving the second untested. DateTimes don’t validate well – When comparing DateTime types, it is often difficult to get accurate results due to the rapid change in the current time and the varying degrees of precision of different time types. I have found it best to use a tolerance wherever possible in my DateTime testing. For example, I have created a custom Constraint for Rhino Mocks called a DateTimeConstraint that allows me to specify the tolerance that I will allow in my tests. That tolerance could be to the millisecond, the second, the minute, or whatever makes sense for that test. Type specific values don’t compare well – An Int32 with a value of 12345 is not the same as an Int64 with the same value. Be careful when comparing data types, even if the value in those types should be the same. It is often best to cast or convert the value with the lesser precision, to the other type. Testing using shared resources is difficult – While there is much discussion about what you call a test that touches the database, or another external resource such as a message queue, there is no doubt that interactions with those types of resources must still be tested. If the database or queue you are using is shared, it is possible that data can be manipulated during your tests, making these tests imprecise at best. Whenever possible, you should isolate these tests by using local resources if possible, or by creating the resources specifically for the test. That is, if in your test you create a message queue using a GUID defined in your test as the name of the queue, then use that for your tests and destroy the queue at the end of the test, you can be reasonably confident that no other user will be manipulating the data in that queue during the test. |
|