I am still retrofitting a whole bunch of unit tests at a client using Pex and Moles. As we have seen in past posts, Pex and Moles are great for creating parameterized unit tests and mock data!
In a conference call this morning, it got brought up that similar to other mocking products in SharePoint development, why all the classes are just not moled (I still don’t know if this is the right verbiage!) and why the heck I am using so many stubs :) . It turned into a lengthy discussion that I wanted to sum up so I can point to this post later!
Firstly, a stub (or more accurately, the stubs framework) is basically a nifty means of static code generation. What this means is a dissimilarity in expectation structured expression trees for testing (the code is generated at runtime [dynamic]). Now, stubs find utility because of efficiency and declarative coverage, the performance benefits coming from the leveraging of virtual method dispatch. Virtual method dispatch is generally more efficient since it already has the this pointer ready to go. When calling through a delegate the this pointer has to be fetched from the delegate. Booooo hisssssss. :) So it’s fast! In the terms of components, Moles lean on the CLR (the profiler more specifically) for the test generation, whereas stubs will use the virtual method approach to overload stuff.
Now, even though the efficiency is pretty impressive, this indubitably doesn’t mean that stubs should continually be used over moles. That is best established by what exactly is being tested. So approach may heavily vary. But, a rule of thumb is if you can use stubs, suck it up, deal with the code bloat, and enjoy the performance benefits! It is always important to still consider what you are testing however, you want to make sure that the unit testing is targeted and is not inadvertently testing unnecessary classes and promotes proper testing!
Oh la la! Combining Pex test with Team Foundation Server is indeed a powerful combination, and boy is it easy as hell to setup. The end state of this type of integration is pretty straightforward, we wanted to repeatedly provision Pex tests when executing build events in TFS.
This is a pretty awesome setup because parameterized units tests can be explicitly created, then the Pex tests can provide all the good stuff on build for the test running. Furthermore, we can even have full coverage by allowing Pex to create some of the tests that we space.
The changes required are minimal since in the build events it simply requires wiring some commands. Assuming that the tests are *already* created, you can use the MSBuild Project AssemblyName property or declaratively provide the assembly wiring the following command into your build event:
This is all fine and good, but what is you want complete coverage to ensure your tests exist? Luckily, Pex provides the /erm:wizard switch to generate the parameterized unit tests, and we can call our explicit tests using the /sa switch. This looks like the following:
pex.exe /erm:wizard test.dll /sa:test.tests.dll
Viola! Getting so easy it’s going to be hard justifying not having Unit Tests!
Pex as covered in past posts is a pretty great white box testing tool. But let’s assume that you want to have a “factory” in the sense that test methods can be automagically built out. An example of this is you have a list of some acceptable data type, and you want harness a test case for each one, and avoid the use of haphazard data keeping in mind that Pex will only use varying values.
In this case, you must push Pex to use parameterized unit tests since you will essentially be targeting a value from a list of values. In the below, I am assuming an array of integers is being populated by the void PopulateIntArray() method. Following, the Test method is defined which has the method decoration of PexMethod which implies it is Pex parameterized unit test. In the method, we are leveraging the PexAssume.IsTrue which means the test case fails if the condition evaluates to false.
static int intArray = PopulateIntArray();
public void Test(int index)
PexAssume.IsTrue(index >= 0 && index < intArray.Length);
int x = intArray[index];
EDIT: As Peli points out in the comments, you can use the PexArguments decoration to pass in values as well.