In an ideal world one would write unit-tests before writing any new code following the tenants of TDD. In reality it is quite common to have to rely on a legacy library to do some heavy lifting. Pex is a great new tool available from Microsoft Research that can be used to generate unit-tests automatically. It is smart in that it runs the function you wish to test trying to exercise all possible code paths and ultimately generates unit-tests that can be used to test that function.
Using Pex is as easy as right-clicking on a function in Visual Studio and selecting “Run Pex Explorations”. Pex takes a little while running your function and then displays a table with various values that can be used to test your function.
However if your legacy code happens to be in VB.NET, you cannot just right-click on a function to have Pex generate all unit-tests for you. So that’s where I hope this article will help you.
First, let’s define a scenario. Imagine there’s a class called Transaction and a class called PaymentMethod. A transaction contains various payment-methods. A PaymentMethod indicates whether it requires the cash-drawer to be opened or not (e.g. it doesn’t make sense to pop cash-drawer for a credit-card while it does for cash and debit-card). There’s a read-only property PopCashDrawer on Transaction which returns true if any of the payment-methods requires the cash-drawer to be opened.
Public Class PaymentMethod
Private mPopCashDrawer As Boolean
Public Property PopCashDrawer() As Boolean
Get
Return Me.mPopCashDrawer
End Get
Set(ByVal value As Boolean)
Me.mPopCashDrawer = value
End Set
End Property
End Class
Public Class Transaction
Private mPaymentMethods() As PaymentMethod
Public Property PaymentMethods() As PaymentMethod()
Get
Return Me.mPaymentMethods
End Get
Set(ByVal value As PaymentMethod())
Me.mPaymentMethods = value
End Set
End Property
Public ReadOnly Property PopCashDrawer() As Boolean
Get
Dim pop = False
For Each pm As PaymentMethod In Me.PaymentMethods
pop = pop OrElse pm.PopCashDrawer
Next
Return pop
End Get
End Property
End Class
To have Pex generate unit-tests for you, here’s what you need to do:
- First to get started writing unit-tests, just right-click on Transaction in Visual Studio and select “Create Unit Tests”. Make sure you select “Create a new Visual C# project” for Output Project in the dialog that pops up.
- Next, in the generated class TransactionTest add the following parameterized unit-test (PUT). This guides Pex to come up with different values of arguments to this method which will exercise all code-paths in PopCashDrawer property. Transaction.PopCashDrawer depends upon the PaymentMethods so we take the array of PaymentMethods as argument to our PUT and set it on the transaction before calling PopCashDrawer. The PexAssume.IsNotNull line further guides Pex to say that we don’t really care about the case when transaction is null because we’re really interested in testing PopCashDrawer method.
[PexMethod]
public bool PopCashDrawerPUT(Transaction transaction, PaymentMethod[] paymentMethods)
{
PexAssume.IsNotNull(transaction);
transaction.PaymentMethods = paymentMethods;
return transaction.PopCashDrawer;
} - Next, just right-click on PopCashDrawerPUT and select “Run Pex Explorations”. Pex will then display a table with various values of arguments and the results it got in each case.
- However since the VB assembly is separate from the C# test-project, Pex will display an icon indicating that it didn’t explore some methods because they were uninstrumented.
- Make sure you include all methods displayed as uninstrumented and run Pex explorations again.
- This time around Pex would show 7 different test-cases that it identified.
- A file named TransactionTest.PopCashDrawerPUT.g.cs would be generated containing unit-tests for those 7 cases. Take a look at that class to see how much work it saved you.
- You can run the generated unit-tests by going to Test->Run->All Tests in Solution from the main-menu in Visual Studio.
- Pex would discover inputs which cause PopCashDrawer to throw a NullReferenceException. Determining fixes for those cases is left as an exercise to the reader
Download and try out Pex, if you haven’t already!







