20.5. Advanced

Up until now, you have seen how to write and execute unit tests. This section goes on to examine how you can add custom properties to a test case, and how you can use the same framework to test private methods and properties.

20.5.1. Custom Properties

The testing framework provides a number of test attributes that you can apply to a method to record additional information about a test case. This information can be edited via the Properties window and updates the appropriate attributes on the test method. There are times when you want to drive your test methods by specifying your own properties, which can also be set using the Properties window. To do this, add TestProperty attributes to the test method. For example, the following code adds two attributes to the test method to enable you to specify an arbitrary date and an expected status. This might be convenient for ad hoc testing using the Test View and Properties window:

<TestMethod()> _
<TestProperty("SpecialDate", "1/1/2008")> _
<TestProperty("SpecialStatus", "Suspended")> _
Public Sub SpecialCurrentStatusTest()
    Dim target As Subscription = New Subscription

    target.PaidUpTo = CDate(Me.TestContext.Properties.Item("SpecialDate"))
    Dim val As Subscription.Status = _
   CType([Enum].Parse(GetType(Subscription.Status), _
   CStr(Me.TestContext.Properties.Item("SpecialStatus"))), _
             Subscription.Status)

    Assert.AreEqual(val, target.CurrentStatus, _
                    "Correct status not set for Paid up date {0}", target.PaidUpTo)
End Sub

By using the Test View to navigate to this test case and accessing the Properties window, you can see that this code generates two additional properties, SpecialDate and SpecialStatus, as shown in Figure 20-8.

Figure 20.8. Figure 20-8

You can use the Properties window to adjust the SpecialDate and SpecialStatus values. Unfortunately, the limitation here is that there is no way to specify the data type for the values. As a result, the property grid displays and enables edits as if they were String data types.

Note one other limitation to using custom properties as defined for the SpecialCurrentStatusTest method. Looking at the code, you can see that you are able to access the property values using the Properties dictionary provided by the TestContext. Unfortunately, although custom properties automatically appear in the Properties window, they are not automatically added to this Properties dictionary. Therefore, you have to do a bit of heavy lifting to extract these properties from the custom attributes list and place them into the Properties dictionary. Luckily, you can do this in the TestInitialize method, as illustrated in the following code. Note that although this method will be executed for each test case in the class, and because of this will load all custom properties, it is not bound to any particular test case, as it uses the TestContext.Name property to look up the test method being executed.

<TestInitialize()> _
    Public Sub Setup()
        Dim t As Type = Me.GetType
        Dim mi As Reflection.MethodInfo = t.GetMethod(Me.TestContext.TestName)
        Dim MyType As Type = GetType(TestPropertyAttribute)
        Dim attributes As Object() = mi.GetCustomAttributes(MyType, False)

        For Each attrib As TestPropertyAttribute In attributes
            Me.TestContext.Properties.Add(attrib.Name, attrib.Value)
        Next
    End Sub

20.5.2. Testing Private Members

One of the selling points of unit testing is that it is particularly effective for testing the internals of your class to ensure that they function correctly. The assumption here is that if each of your classes works in isolation, then there is a better chance that they will work together correctly; and in fact, you can use unit testing to test classes working together. However, you might be wondering how well the unit-testing framework handles testing private methods.

One of the features of the .NET Framework is the capability to reflect over any type that has been loaded into memory and to execute any member regardless of its accessibility. This functionality does come at a performance cost, as the reflection calls obviously include an additional level of redirection, which can prove costly if done frequently. Nonetheless, for testing, reflection enables you to call into the inner workings of a class and not worry about the potential performance penalties for making those calls.

The other, more significant issue with using reflection to access nonpublic members of a class is that the code to do so is somewhat messy. Fortunately, Visual Studio 2008 does a very good job of generating a wrapper class that makes testing even private methods easy. To show this, return to the CurrentStatus property, change its access from public to private, and rename it PrivateCurrentStatus. Then regenerate the unit test for this property as you did earlier.

The following code snippet is the new unit-test method that is generated:

<TestMethod(), _
DeploymentItem("TestingWinFormsApp.exe")> _
Public Sub PrivateCurrentStatusTest()
    Dim target As Subscription_Accessor = New Subscription_Accessor
    Dim actual As Subscription.Status
    actual = target.PrivateCurrentStatus
    Assert.Inconclusive("Verify the correctness of this test method.")
End Sub

As you can see, the preceding example uses an instance of a new Subscription_Accessor class to access the PrivateCurrentStatus property. This is a class that was auto-generated and compiled into a new assembly by Visual Studio. A new file was also added to the test project, called TestingWinFormsApp.accessor, which is what causes Visual Studio to create the new accessor classes.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.5.15