Thursday, May 08, 2008
posted on Thursday, May 08, 2008 10:40:27 PM UTC  #    Comments [0]
 Wednesday, February 27, 2008

This is one problem for which we don't have an elegant solution yet:

what is the best way to craft a name for a generated test?

Let's see an example; given the following parameterized unit test,

[PexMethod] void Test(int i) {
    if (i == 123) throw ArgumentException();
}

Pex would generate 2 tests: i = 0, i = 123. So it seems doable to infer test names such as

[TestMethod] void Test0() { this.Test(0); }
[TestMethod, EE(typeof(ArgumentException))]
void Test123ThrowsArgumentException() { this.Test(123); }

So what's so difficult about it? Well, most PUT's aren't that simple and as the size of the generated parameter increases, the methods might increase as well (strings getting bigger). Here's a list of potential problems:

  • the method should stay relatively small (less than 80 chars),
  • the parameters might be objects or classes, which do look well in a string format,
  • generated strings might be huge and contain weird unicode characters,
  • the tests might involve mock choices which again do not render well to strings,
  • the more parameters the more cryptic things become

Our approach: Timestamps

To the light of all those problems, we've taken the shortcut route in Pex by simply using combination of the parameterized unit test method signature and the timestamp when the test is generated:

[TestMethod] void TestInt32_20080224_124301_35() { ... }

This is ugly, how can I change that?

We've added an extensibility point to support custom test naming scheme. After registering your 'namer', you will get opportunity to craft a test name following your favorite code standard. You will have the generated test, output, exception, etc... at your disposition to make an intelligent choice there.

Off course, you're also welcome to drop a comment on this post to suggest a better scheme.

posted on Wednesday, February 27, 2008 4:18:46 PM UTC  #    Comments [2]
 Saturday, February 23, 2008

So how do you write negative test cases with Pex? Here's a nice solution I was working on. I'm wondering

Traditional ExpectedExceptions style

Let's test the constructor a type Foo that takes a reference argument. We expect to throw a ArgumentNullException when null is passed. Therefore, we could write

[ExpectedException(typeof(ArgumentNullException))]
void Test() {
     new Foo(null);
}

or using xUnit style assertions,

void Test() {
     Assert.Throws(delegate { new Foo(null); });
}

Pex ExpectedExcetions style

Let's refactor our first test and push 'null' as a test parameter. We add an assertion after the constructor to make sure a null parameter never succeeds.

void Test(object input) {
    new Foo(input);
    Assert.IsNotNul(input); // we should never get here
}

The interesting part is that this test will not only test for the null value but also for the passing values as well. Moreover, there might be more checks over the input which might trigger other exceptions. In that case, additional asserts could be added -- or even better, centralized in an invariant method.

So, what do you think?

posted on Saturday, February 23, 2008 5:40:50 PM UTC  #    Comments [2]
 Saturday, February 16, 2008

Looks like I've just made it in for the Seattle ALT.NET 'un'-conference :)

posted on Sunday, February 17, 2008 7:02:01 AM UTC  #    Comments [0]
 Friday, February 15, 2008

Some may wonder if there's any relation between my nickname 'Peli' and 'Pex': there's none! Pex just stands for "Program Exploration".

In fact, Pex was started long before I joined the project by my colleague Nikolai Tillmann. Nikolai started the MUTT project (read this), which is the ancestor of Pex. He's the mastermind behind the IL rewriter, symbolic engine, and well a large part of Pex :) Hopefully, I'll convince him to start a blog :).

posted on Saturday, February 16, 2008 2:43:55 AM UTC  #    Comments [0]
 Wednesday, February 13, 2008

Maybe yes, maybe no, I guess it depends on the reviews... Have you reviewed it?

http://submissions.agile2008.org/node/2766

posted on Thursday, February 14, 2008 6:53:49 AM UTC  #    Comments [0]

This is a general recommendation if you're planning to use a tool like Pex in the future: make sure that preconditions (i.e. parameter validation) fails in a different fashion that other assertions.

Here's a snippet that shows the problem:

// don't do this
void Clone(ICloneable o) {
     Debug.Assert(o != null); // pre-condition
     ...
     object clone = o.Clone();
     Debug.Assert(clone); // assertion
}

Why is this bad?

A tool like Pex will explore your code and try to trigger every Debug.Assert it finds on its way. When the assertion is a precondition, it is likely expected and one would like to emit a negative test case (i.e. 'expected exception').

The problem in the snippet above is that both failure will yield to the same assertion exception and it will very difficult to *automatically* triage the failure as expected or not.

How do I fix this?

Make sure different classes of assertions can be differentiated automatically, through different exception types, tags in the message, etc...

posted on Thursday, February 14, 2008 1:51:00 AM UTC  #    Comments [3]
 Friday, February 01, 2008

The bus that rides from Redmond to Seattle now has an excellent WiFi/Internet support. It helps killing the time when traffic gets really bad... For example, I can look at my bus through the network of king county webcams :)

posted on Friday, February 01, 2008 12:30:12 PM UTC  #    Comments [0]
 Saturday, December 22, 2007

Scott swinged by MSR a couple weeks ago to talk about Pex.

http://hanselminutes.com/default.aspx?showID=111

 

posted on Saturday, December 22, 2007 8:02:30 PM UTC  #    Comments [0]
 Thursday, December 06, 2007

Update: this talk has been cancelled.

I'll be giving a talk about Pex in Diegem on January 3.

http://msdnrss.thecoderblogs.com/2007/12/06/msdn-techtalk-dynamic-analysis-and-test-generation-for-net-with-pex/

posted on Friday, December 07, 2007 12:33:33 AM UTC  #    Comments [0]
 Wednesday, December 05, 2007

In the previous post, we went through the exploration testing process to exercise a simple method, CheckPositive. In this post, we'll try the same exploration testing, but will let Pex do it.

// mehod under test
1 void CheckPositive(int i, bool @throw) {
2     if (i < 0) {      
3          Console.WriteLine("not ok");
4          if (@throw)
5             throw new ArgumentException();
6     }
7     else
8         Console.WriteLine("ok");
9 }
// hand-crafted unit tests
[TestMethod] void Zero() {
     CheckPositive(0, false);
}
[TestMethod] void MinusOne() {
     CheckPositive(-1, false);
}
[TestMethod] void MinusOneAndThrow() {
     CheckPositive(-1, true);
}

Exploration testing with Pex

To let Pex explore the CheckPositive, we write a little test wrapper around that method:

[TestClass, PexClass]
public partial class ExplorationTesting {
    [PexMethod]
    public void Test(int i, bool @throw) {
        CheckPositive(i, @throw);
    }

We also instrumented the original method with additional methods to track down the path conditions that Pex computes along the execution traces. Pex generates 3 pairs of values which are equivalent to what the test we manually created:

  • 0, false
  • int.MinValue, false
  • int.MinValue, true (throws)
posted on Thursday, December 06, 2007 12:54:15 AM UTC  #    Comments [1]
 Tuesday, December 04, 2007

In the previous post, we clarified what Pex was not doing. So what does it do?

Pex performs some kind of automated exploration testing. I'll dive deeper into the details of this, but let's start with an example that gives the high level idea of the methodology.

Exploration Testing

Let's start by doing some exploration testing on a simple method that checks that an integer is positive, CheckPositive:

1 void CheckPositive(int i, bool @throw) {
2     if (i < 0) {      
3          Console.WriteLine("not ok");
4          if (@throw)
5             throw new ArgumentException();
6     }
7     else
8         Console.WriteLine("ok");
9 }

One way to 'explore' this method would be to throw different values at CheckPositive and use the debugger to see what's happening.

Iteration 1: pick the default

Let's create a unit test that does exactly that and step into the debugger. Since we don't really know anything about CheckPositive yet, we simply pick 0 for i (actually default(int)).

[TestMethod]
void Zero() {
     CheckPositive(0, false);
}

When we reach the statement "Console.WriteLine..." on line 8, we can figure out that we took this branch because the condition "i < 0" on line 2 evaluated to false. Let's remember this and continue on.
          line 2, i < 0 == false, uncovered branch

The execution continues and the test finished successfully.

Iteration 2: flip the last condition

In the previous run, we've remembered that some code was not covered on line 3. We also know that this code path was not covered because the condition "i < 0" evaluated to false. At this point, we usually intuitively figure out a value of 'i' in our brain, to make this condition true. In this case, we need to solve "find i such that i < 0". Let's pick -1.

[TestMethod]
void MinusOne() {
     CheckPositive(-1, false);
}

We run the test under the debugger. As expected on line 2, the condition evaluates to true, and the program takes the other branch that in the previous test.
The program continues and reaches line 4 where another if statement branch. Since the condition  "@throw" evaluates to false, we take the branch that throws and remember the condition:
          line 4, @throw == false, uncovered branch

The program continues to run and finishes.

Iteration 3: path condition + flipped condition

We've still some uncovered branch to cover in the method, 'guarded' by the condition at line 4. To be able to cover this code, we need 2 things:
      1) reach line 4: i < 0
      2) make the condition in line 4 evaluate to true: @throw == true

So to cover the last statement in the method, we need to find parameter values such that
                  i < 0 && @throw == true

Let's pick -1, and true.

[TestMethod]
void MinusOneAndThrow() {
     CheckPositive(-1, true);
}

The test executes and now throws an exception as we wanted. At this point, we've fully covered to behavior of CheckPositive.

What about Pex?

Pex uses the same 'exploration' methodology as above. Pex executes a parameterized unit tests over and over and tries to cover each branch of the program. As it executes more code, it learns about new branches to cover etc... To find the input, Pex uses a constraint solver, Z3.

posted on Wednesday, December 05, 2007 3:17:38 AM UTC  #    Comments [2]

Nikolai Tillmann published a paper on DySy, a tool that can infer likely invariants by monitoring the code that is running.

DySy is was built on top of the infrastructure that Pex uses to generate test cases. In fact, it is one of our sample application :)

posted on Wednesday, December 05, 2007 12:53:17 AM UTC  #    Comments [0]
 Friday, November 30, 2007

I realized that I had not talked much about how Pex computes the values for the test parameters... the most important part of the tool!

It's not ...

Let's start by getting to wrong ideas out of the way. Parameterized tests are nothing new, they exist in MbUnit, VSTS, XUnit.Net, FIT, etc... so what's different with Pex?

  • it is not random: when it comes to generate data, the easiest solution is to plugin a random generator. If the state space is big enough (e.g. integers 2^32), it highly unlikely that random tests will find the interesting corner cases,

if (i == 123456)
     throw new Exception(); <---------- random won't find this

  • it does not require ranges or hints for the data: Pex does not require annotation to specify the range of particular inputs. All the relevant input values are inferred from the code itself (we'll see later how).
  • it is not pairwize testing: following the comment above, Pex does use a pairwize approach.
  • it is not data testing: data testing such as FIT or MbUnit RowTest usually consists of rows containing a set of inputs and the expected output. In Pex, you cannot provide the expected output as a 'concrete' value, you need to express it as code (through assertions for example). This is a subtle difference that radically changes the way you write your tests.

[RowTest, Row(0, 1, 1), Row(1, 0, 1)] // data test for the addition
void AddTest(int a, int b, int result)
{   Assert.AreEqual(result, a + b);  }

[PexMethod] // 0 is the neutral of the addition operation
void ZeroNeutralTest(int b)
{   Assert.AreEqual(b, 0 + b);  }

  • it is not a static analysis tool: Pex does a dynamic analysis of the code; it analyses the code that *is* running. Pex does this by rewriting the IL before it's jitted and instrumenting it with (many) callbacks to track precisely which IL instruction is being run by the CLR. So yes, Pex analyses the IL but on the fly rather than 'statically'.

Ok, now we've got a better idea of what Pex is not. So how does it work? ....

posted on Friday, November 30, 2007 5:19:05 PM UTC  #    Comments [3]
 Friday, October 19, 2007

In it's Weekly Source Code, Scott Hanselman presents a new CodePlex project, NDepend.Helpers.FileDirectoryPath from Patrick Smacchia. Nice, better path handling should have been part of the BCL a while ago. 

Path stuff is hard

Path normalization and parsing is not an easy task so when Patrick Smacchia mentions that his code "100% unit-tested", I decided to see if Pex could not find a little bug over there.

A dumb parameterized unit test

So I added wrote the following parameterized unit test, which 'simply' calls the constructor of FilePathRelative. Under the hood, there is some string manipulation done by the library to normalize the path, it should be interresting to see what comes out of this. I also added calls to PexComment.XXX to log the input/output values (Pex will build a table out of this):

    [PexMethod]
    public void FilePathRelativeCtor(string path) {
        PexComment.Parameters(path);
        FilePath result = new FilePathRelative(path);
        PexComment.Value("result", result.FileName);
    }

Ooops

So Pex starts running and soon enough an assert pops up. Pex had just found a neat little path that broke an assertion in the library:

[Test]
public void FilePathRelativeCtor_String_71019_003302_0_05() {
    this.FilePathRelativeCtor("/");
}

Popping up the reports, I went for the parameter table (remember the PexComment calls) that shows one row for each generated test. In fact, the 5-th test that Pex generated was triggering the assert:

Note that "//" also triggers the bug which seems to indicate that any path finishing by "/" will have this behavior.

The path condition

Lastly, I took a quick look at the path condition that Pex solved to discover the bug (see red below). Luckily this one is fairly easy and one can clearly see 'path[0] == '/' in there.

 What did we learn today?

Handling paths is hard :)

Also, we saw that a dumb parameterized unit test (just calling a ctor), could find a bugs. If you use assertions, it will help Pex look for bugs in your code.

posted on Friday, October 19, 2007 3:46:37 PM UTC  #    Comments [3]
 Wednesday, October 17, 2007

Update: I will not be at the Seattle Code Camp, too much rescheduling.

I'll be presenting Pex at the Seattle Code Camp in Nov.

Pex – Automated White Box Unit Testing

Parameterized unit testing is becoming a mainstream feature of most unit test frameworks; MbUnit RowTest (and more), VSTS data tests, xUnit.net Theories, etc... Unfortunately, it is still the responsibility of the developer to figure out relevant parameter values to exercise the code. With Pex, this is no longer true. Pex is a unit test framework addin that can generate relevant parameter values for parameterized unit tests. Pex uses an automated white box analysis (i.e. it monitors the code execution at runtime) to systematically explore every branches in the code. In this talk, Peli will give an overview of the technology behind Pex (with juicy low-level .NET profiling goodness), then quickly jump to exiting live demos.

posted on Wednesday, October 17, 2007 8:36:52 AM UTC  #    Comments [0]
 Thursday, October 11, 2007

When someone is writing a book that contains code snippets, the question of (automatically) keeping those in sync quickly becomes very imporant. There's already lots of different solutions to this problem (every author has probably it's own), here's yet another one for C# that we've developed to author the Pex documentation.

Goals

A couple things that we wanted to acheive with this tool:

  • snippets are always compilable and run as expected,
  • snippets can be full classes, methods or even partial statements
  • simple :)

'#region' based solution

This solution uses the #region directive to define a snippet. The region describe contains the snippet name, which will be used to dump it into a file. For example, given this piece of C#,

...
#region snippet StackExamplePart3
stack.Push(new object);
#endregion
...

Our parse will extract the code in the region and write it to StackExamplePart3.tex, which gets pulled in our LaTeX scripts.

\begin{verbatim}
stack.Push(new object);
\end{verbatim}

That's it?

Yes, you can author snippets that stay compilable and up to date:

  • we can author all the snippets in Visual Studio and we are sure they always compile
  • it's very easy to parse the #region's (left as exercise ;))
  • #region are very flexible in terms what they contain so we can have snippets containing partial methods, statement, etc...
  • the scheme aslo supports nested regions which is usefull when one explains an example line by line, and integrate the entire sample at the end. For example, DeclaringUnitTest is a 'sub'-snippet of UnitTest:
#region snippet UnitTest
#region snippet DeclaringUnitTest
[TestMethod]
void Test(int i)
#endregion
{
   
}
#endregion
  • we can integrate our snippets in unit tests and verify they work as expected
  • the tool can be integrated into the build process as a post-command build

 

posted on Thursday, October 11, 2007 1:41:32 PM UTC  #    Comments [2]
 Sunday, September 30, 2007

In Pex, we have our own version of all (and more) collection classes from the BCL. This duplication may sound stupid but there's a very good reason behind it: since Pex instruments code (i.e. rewrites IL), the BCL collections might be instrumented as well... leading to a poorer performance (instrumented code is slower for many reasons). Therefore, to avoid this situation, we ended up using our own implementation which never gets instrumented.

While using our collections, we added 2 features that we like a lot: readonly interfaces and small collections.

Readonly interfaces

Readonly interfaces are handy to 'safely' expose collections, once you start using them you get hooked:

  • ICountable<T>, a readonly enumerable with a Count.
interface ICountable<T> : IEnumerable<T>
{
    int Count {get;}
}
  • ICopyable<T>, a countable that can be copied around,
interface ICopyable<T> : ICountable<T>
{
    void CopyTo(T[] array, int index);
}
  • IIndexable<T>, a indexed collection
interface IIndexable<T> :  ICopyable<T>
{
    T this[int index] { get; }
}

We also have a couple more interfaces for dictionary style collections but you get the idea.

Small Collections

Small collections are optimized collections with 0, 1 or 2 elements. Depending on your scenario, these can improve the performance of your application while lowering the pressure on the GC (create less objects -> less stuff to garbage collect). If you create a lot of objects which each have collections, ask yourself: are you lazy allocating the collections? what should be the initial size of the collection? do you expect more than one element on average?

posted on Sunday, September 30, 2007 1:33:15 PM UTC  #    Comments [0]
 Sunday, September 23, 2007

xUnit, the new variation on the 'unit test framework' theme comes with support for data driven tests: 'Theories' (funny name by btw). Pex is a plugin for test frameworks, so we've added support for xUnit as well.

[PexClass] // xUnit does not have fixture attributes
public class MyTests
{
    [Theory, DataViaXXXX] // xUnit theories
    [PexTest] // let pex help you 
    public void Test(int a, ....)
    {}
}

posted on Sunday, September 23, 2007 11:26:32 PM UTC  #    Comments [0]
 Friday, September 14, 2007

Z3 is the high performance theorem prover that Pex uses to solve constraint systems (and find bugs). You can now play with it too! 

http://research.microsoft.com/projects/z3/

Z3 is written in C++, but it has a .Net API to make you happy.

posted on Friday, September 14, 2007 7:01:41 AM UTC  #    Comments [1]
 Saturday, September 08, 2007

In a previous, we were looking at partial trust the lack of support for it. In this post, I'll show the key 'fixes' that we did to make Pex 'partial trust' aware.

Simulating Partial Trust

The easiest way to run under partial trust is to run your .net application from the network. However, in the context of a test framework, this would not work since many required permissions would not be granted (reflection, i/o, etc...). So we need a new AppDomain whose security policy considers the test framework assemblies as fully trusted.

  • Get a new AppDomain:
string trust = "LocalIntranet";
AppDomain domain = AppDomain.CreateAppDomain(trust);
  • Load the named permission set
PermissionSet permission = GetNamedPermissionSet(trust);
  • Create the code group structure that associate the partial trust permission to any code
UnionCodeGroup code= new UnionCodeGroup(
    new AllMembershipCondition(),
    new PolicyStatement(permission, PolicyStatementAttribute.Nothing));
  • give full trust to each test framework assembly:
StrongName strongName = CreateStrongName(typeof(TestFixtureAttribute).Assembly);
PermissionSet fullTrust = new PermissionSet(PermissionState.Unrestricted);
UnionCodeGroup fullTrustCode = new UnionCodeGroup(
new StrongNameMembershipCondition(strongName.PublicKey, strongName.Name, strongName.Version),
new PolicyStatement(fullTrust, PolicyStatementAttribute.Nothing));
code.AddChild(fullTrustCode);
  • Assign the policy to the AppDomain
PolicyLevel policy = PolicyLevel.CreateAppDomainLevel();
policy.RootCodeGroup = code;
domain.SetAppDomainPolicy(policy);

This is basically it (the rest of the details are left as an exercise :)).

Let them call you

Make sure to add the AllowPartiallyTrustedCallers to the test framework assembly otherwize users won't be allowed to call into it...

A twist...

Pex is bit invasive when it comes to partial trust. Pex rewrites the IL at runtime and turns all method bodies into... unsafe code (that is unverifiable). At this point, any will not run because of the SkipVerification permission.

No problemo, just add it to the permissionset:

permission.AddPermission(
    new SecurityPermission(SecurityPermissionFlag.SkipVerification)
    );

 

posted on Saturday, September 08, 2007 1:39:22 PM UTC  #    Comments [0]
 Wednesday, September 05, 2007

Writing code that will run in partial trust is tricky... and writing unit tests for it turns out to be even trickier. Does your favorite unit test framework support partial trust?

After looking on NUnit, MbUnit or VSTT, it did not look like so (if I overlooked this feature, don't hesitate to point it out to me). No magic command line flag or custom attribute to get the work done.

Even more interesting, the test framework assemblies don't have the AllowPartiallyTrustedCallersAttribute... so you can't even use their assertion classes in partial trust as it will trigger a SecurityException... Good stuff.

posted on Wednesday, September 05, 2007 12:01:05 PM UTC  #    Comments [1]
 Thursday, August 23, 2007

A common requirement for unit test framework is the ability to test internal types.

That's easy! use InternalsVisibleToAttribute

With .Net 2.0 and up, this is a fairly easy task thanks to the InternalsVisibleToAttribute: add it to the product assembly to give 'visibility rights' to the test assembly.

// in assembly Foo
internal class Foo {}
// giving visibility rights to the Foo.Tests assembly
[assembly:InternalsVisibleTo("Foo.Tests")]

On the test assembly side, this works because unit test are 'closed' methods which do not expose any internal types.


[Test]
public void FooTest() {
    Foo foo = new Foo(); // we're using the internal type Foo
                         // but it's hidden in the unit test
}

What about parameterized tests? Make them internal as well

If one of the parameters of the test is internal, the test method will have to be internal as well in order to compile:

[PexTest]
internal void FooTest(Foo foo) {
   ...
}

Not pretty but still gets the job done. Pex will generate public unit test methods that invoke the internal parameterized test method, and we'll be happy:

[Test]
public void FooTest_12345() {
    this.FooTest(null);
}

What about MbUnit RowTest?

This issue was never faced by MbUnit RowTest because it only accepts intrinsic types such as int, long, etc... Those types are obviously public :)

posted on Friday, August 24, 2007 12:24:08 AM UTC  #    Comments [0]

Finally found the time and motivation to upgrade the Reflection.Emit language to Reflector 5.0. Available now at http://www.codeplex.com/reflectoraddins .

image

posted on Thursday, August 23, 2007 7:26:55 AM UTC  #    Comments [1]
 Saturday, July 14, 2007

Pex can analyze regular expressions*** and generate strings that matches them automatically!

What does it mean? Well, maybe, somewhere deep in your code your are validating some string with a regex (for example a url). In order to test the validation code, one needs to craft inputs that does not match (easy) and matches (harder) the regex.

Let Pex do it:

So what if Pex could be smart enough to understand a regex and craft inputs accordingly? In the example below, it would be very hard for a random generate to generate a string that matches the regex.

[PexTest]
public void Url([PexAssumeIsNotNull]string s)
{
    if (Regex.IsMatch(s, "(?<Protocol>\w+):\/\/(?<Domain>[\w@][\w.:@]+)\/?[\w\.?=%&=\-@/$,]*"))
        throw new PexCoverThisException(); // random won't find this
}

"" would be a failing match and foo://foo.com a good match. (To generate the correct match, my brain simulated the regex automaton and estimated one possible path). Interestingly, Pex generates....

Ā://Āā

Pretty ugly... but correct! This reminds us that while regex are used to validate input, what they'll let through is sometimes scary.

Compiled Regex + Pex = Love

The great part about supporting the regular expressions is that it comes for free (almost) since Regex can be compiled to IL in .Net. When the BCL generates the regex IL code, it effectily builds the automaton... which can be analyzed by Pex!!!

Refresher: Pex works analyzing the MSIL being executed.

Hey but not all Regex are compiled!

That's true. Compiling the regex is optional so Pex needs to do a little bit of 'plumbing' to make sure all regular expressions are compiled. This is simply done by substituting the real .ctor of the Regex class with a customized version that compiles the regex. I'll talk about substitutions deeper in the future.

*** Of course, the bigger the regex is, the harder it is going to be for Pex to craft a successful match.

posted on Sunday, July 15, 2007 4:49:53 AM UTC  #    Comments [1]
 Sunday, July 08, 2007

I finally posted a project that I had been developing last year in my daily commutes: Toad (www.codeplex.com/toad).

Toad is an (experimental) compiler infrastructure to build languages top of .Net, without knowing much about IL. Mostly it was a way for me to learn first hand all the little subtleties of writing multiple language on top of .Net.

What does Toad give you?

  • A dynamic console that supports multiple languages,
  • An Expression/Statement tree that can be translated back to IL,
  • Built-in debugging capabilities,
  • A set of Visitors on top this AST that implement various optimization and language constructs (this is the fun part),
  • There's a lot of stuff, I used to take the bus twice a day. :)
  • Toad does not use the DLR maybe in the future.

What is it good for?

  • Toy around with IL and try to build your micro language.
  • Don't use it for anything serious.

Good For Nothing Language

 The 'Good for nothing' language is a toy language that Joel Pobar used to illustrate managed IL compilers. With Gfn, you can write simple program such as:

var i = 123;
print i;
for j = i to 10 do print i+j; end;

The parsing stuff

I took Joel's example and wrote a grammar for the Gold parser. It looks like something like this that is then compiled by Gold:

<Program> ::= <BlockStatement>

<BlockStatement> ::= <BlockStatement> <Statement> ';'
            | <Statement> ';'

<Statement> ::= 'var' Identifier '=' <Expression>
    | Identifier '=' <Expression>
    | 'for' Identifier '=' <Expression> 'to' <Expression> 'do' <BlockStatement> 'end'
    | 'read_int' Identifier
    | 'print' <Expression>
    | 'return' <Expression>

At the end of the process, you get a visitor for the code AST. This is the boiler plate code to start using Toad to build the compiler:

// <Statement> ::= for Identifier '=' <Expression> to <Expression> do <BlockStatement> end
protected virtual object VisitRuleStatementforIdentifierEqtodoend(SyntaxNode node)
{
     throw new NotSupportedException("RuleStatementforIdentifierEqtodoend");
}

Implementing the 'for' loop

Let's take a look at the implementation of the for loop. We need to:

  • extract the from, to expressions,
  • declare a variable for the index,
  • build the predicate i < to etc...,
  • emit symbols for debugging,

The code below shows the full implementation of that statement:

// <Statement> ::= for Identifier '=' <Expression> to <Expression> do <BlockStatement> end
protected override object VisitRuleStatementforIdentifierEqtodoend(SyntaxNode node)
{
    // from, to
    Expression from = (Expression)this.VisitNode(node[3]);
    Expression to = (Expression)this.VisitNode(node[5]);

    // x = from
    VariableDeclarationStatement init = Stm.Var(node[1].Data, from);

    // body
    this.Context.PushScope();
    this.Context.PushVariable(init.Variable);

    Unit body = (Unit)this.VisitNode(node[7]);

    // i < to;
    Expression ilto = Expr.LessThanOrEqual(Expr.Var(init), to);
    ilto.Symbol = FromNode(node[1]);
    // ++i
    Statement inc = Stm.Expr(Expr.PrePlusPlus(Expr.Var(init)));

    this.Context.PopScope();

    ForStatement forstm = Stm.For(init, ilto, inc);
    forstm.Body = Stm.FromUnit(body);

    return forstm;
}

Hooking up the visitor in Toad

The last step is to package our visitor as a 'language' and return the generated statements or expression to Toad. We can spin up the interactive console, load Gfn and try it out:

image

Nothing really mind blowing here. Let's turn on live IL debugging to see what happening under the hood. This mode emits the IL source of the method, adds a bunch of 'nop' instructions to force the debugger to step on each IL instruction:

image

You can see in the generated code how the expressions got translated into IL instructions. 

posted on Monday, July 09, 2007 5:23:32 AM UTC  #    Comments [0]
 Thursday, July 05, 2007

Pex has a couple samples that get bundled in our installer. We have them in our main solution so that we get the benefits of Refactoring (that they still compiled :)). This approach has one little problem: the sample projects are referencing the Pex projects... which are not shipped! If packaged as is, they'll never compile on the user's machine.

ProjectReference -> Reference

We solved this problem by implementing an MSBuild task that 'patches' .csproj project files by replacing ProjectReference nodes with Reference:

<ProjectReference Include="..\..\..\Pex\Framework\Microsoft.Pex.Framework.csproj">
  ...
</ProjectReference>

becomes

<Reference Include="Microsoft.Pex.Framework">...</Reference>

There's a bit of coding involved to it (resolving the assembly name, selecting the appropriate projects, etc...) but that's basically it :)

posted on Thursday, July 05, 2007 11:02:38 PM UTC  #    Comments [0]
 Wednesday, July 04, 2007

One of the problem with Pex is that.... it's yet another dependency in your test project. Pex has it's own attributes which makes it very difficult to 'strip it out' of the test source. Many teams won't allow to check-in assemblies, they won't install external components on the build machine and just forget about touching the source code!

So how do you strip Pex?

In "Condition" lies the answer

An elegant solution uses a bit of Reflection, CodeDom and the MSBuild Condition attribute: generate Attribute stubs (shadows) and bind them to the project.

Pex modifies the project file and uses MSBuild conditions to conditionally include files and assembly references in the generated test project.

  • A boolean property PexShadows to controls the shadowing state: true if shadowed, false or missing otherwize.
<Project DefaultTargets="Build" ...>
  <PropertyGroup>
    ...
    <PexShadows>true</PexShadows>
  </PropertyGroup>
  • a conditional reference to Microsoft.Pex.Framework:
    <Reference 
        Include="Microsoft.Pex.Framework" 
        Condition="$(PexShadows) != 'true'" />

when the property PexShadows evalutes to true, the Microsoft.Pex.Framework assembly is not referenced anymore.

  • a file containing all the custom attributes 'stubs' (for all attributes in the Microsoft.Pex.Framework) is generated (automatically of course :)). Pex also dumps the source of several other helper classes. Each generated file is added to the test project conditionally:
    <Compile Include="Properties\PexAttributes.cs" Condition="$(PexShadows) == 'true'">
      <AutoGen>True</AutoGen>
      <DependentUpon>AssemblyInfo.cs</DependentUpon>
    </Compile>

That's it! Flip the value of PexShadows to bind/unbing your test project from Pex.

So what does Visual Studio says ?

Visual Studio is totally fooled by the maneuver. It shows the conditional files and references as if nothing happened. Add a menu item in the project context menu to switch it on and off and we are good to go :)

posted on Wednesday, July 04, 2007 12:28:12 PM UTC  #    Comments [0]
 Saturday, June 30, 2007

In Pex, we added the possibility to specify the type under test of a given fixture:

public class Account {...}


[TestFixture, PexClass(typeof(Account))]
public class AccountTest {...}  

That's nice but why would it be useful... Beyond the fact that it clearly expresses the 'target' of the fixture, this kind of information can be leverage by tools like Pex.

For example, since we know that Account is the type under test, we can tune Pex to prioritize the exploration of the Account type.

Another interesting side effect is the targeted code coverage data. Instead of getting coverage information over the entire assembly, we can directly provide coverage over the type under test: the AccountTest covered xx% of Account.

Still toying around the concept, one can add a special filtering mode to the command line to execute all tests that target 'Account':

pex.exe /type-under-test:Account Bank.Tests.dll
posted on Saturday, June 30, 2007 2:23:24 PM UTC  #    Comments [0]
 Sunday, June 03, 2007

A nice side effect of the Pex infrastructure is that it computes coverage data while exploring a parameterized test. What does this mean to the user? Well, what about this specifying that a parameterized test should reach 100% coverage**:

[PexTest]
[PexExpectedCoverage(100)] // expect 100% coverage
public void UberTest(int i)
{ ... }
** What kind of coverage are we talking about?

Pex internally tracks implicit branch coverage (which can never be covered :)). So we usually refer to basic block coverage. By default, the coverage is reported for the code that was run by the parameterized test. This is a very important difference with usual coverage tools, which give numbers for the entire assembly.

posted on Sunday, June 03, 2007 12:24:56 PM UTC  #    Comments [0]
 Saturday, June 02, 2007

This post gives a little introduction on the integrated mock support in Pex (it should also make clear why we couldn't reuse existing (and excellent) mock framework).

As other frameworks, Pex support mocking interfaces or virtual methods in non sealed classes.

Choose and replay

Pex Mocks have 2 modes of execution that are quite different:

  • when Pex is looking for new input, they act as a source of parameter choices, (this will be clearer in the example below).
  • when executing the generated unit tests, they act as stubs.
Micro example

Let us illustrate this by mocking a simple interface that returns the name of an instance:

interface INamed
{
    string GetName();
}
Writing the mock

The mock for this interface looks as follows:

[PexMock] // specifies to pex that this type is a mock
public class MNamed : INamed
{
    public string GetName()
    {
        IPexMethodCallOracle call = PexOracle.MethodCall(this);
        // let's ask Pex for a name    
        return call.ChooseResult<string>(); 
    }
}

So what did we do really: The mock implementation of GetName fetches a value oracle,  an interface from which new values can be queried:

IPexMethodCallOracle call = PexOracle.MethodCall(this); 

Then, this oracle can be used to choose new values. It's like adding parameters to the test, but not through the test signature. In this case, we ask Pex to get a new result value. Pex will choose that value as if it was a parameter of the test:

return call.ChooseResult<string>();
Let's try it!

The following test takes a INamed instance (which we assumed to be non-null) and displays a message on the console if the name is equal to'Marc':

[PexTest]
public void GetName(INamed name)
{
    if (name.GetName() == "Marc")
        Console.WriteLine("hello marc");
}
Generated tests

Pex generates 2 unit tests that fully covers the code of method: Pex tracked the data returned by ChooseResult and computed that this value had to be equal to "Marc" to hit a different path in the execution.

The first test has GetName return a default value. The second generated test is more interresting as it shows how Pex sets up the behavior of the replay stub:

// test 2
MockTest.MNamed mn0 = new MockTest.MNamed();
IPexOracleRecorder oracle = PexOracle.NewTest();
oracle.OnCall(0, typeof(MockTest.MNamed), "GetName")
      .Returns("Marc");
this.GetName(mn0);

The oracle instance is used to set up the result value on the first call to GetName:

// on the call '0' to the method GetName of MockType.MNamed,
oracle.OnCall(0, typeof(MockTest.MNamed), "GetName")
      // return "Marc"
      .Returns("Marc");
Adding behavior

Behavior can simply be added to mock as code since Pex will explore the mock code as well. For example, let's refine the MNamed implementation to always return the same name:

[PexMock] // specifies to pex that this type is a mock
public class MNamed : INamed
{
    private string name;
    public string GetName()
    {
        if(this.name == null)
            this.name = PexOracle.MethodCall(this)
                              .ChooseNotNull<string>("name");
        return this.name;
    }
}
Wrapping Up

In this post, we've given a brief glimpse at the pex oracles. These are a special breed of mocks specific to Pex.

posted on Saturday, June 02, 2007 2:00:50 PM UTC  #    Comments [0]
 Sunday, May 27, 2007

.Net 2.0 has been out for a while and it seems that 'generics' have not made it into unit test frameworks (that I know of). When I write unit tests for generics, I don't want to have to instantiate them!

For example, if I have an generic interface,

interface IFoo<T> {...}

then I'd really like to write this kind of test and let the test framework figure out an interresting instantiation (i.e. choice of T):

[Test]
public void Test<T>(IFoo<T> foo) { ... }

In the example above, System.Object can be trivially used to instantiate IFoo<T>. Of course, things get more interresting when mixing type argument, method argument and constraints :)

interface IFoo<T>
{
    R Bar<R>(T t)
     where R : IEnumerable<T>
}

In Pex, we've started to look at this problem... stay tuned.

posted on Sunday, May 27, 2007 1:09:00 PM UTC  #    Comments [3]
 Friday, May 25, 2007

MbUnit 2.4 is out, check it out at

http://weblogs.asp.net/astopford/archive/2007/05/24/mbunit-2-4-rtm.aspx

If you are using MbUnit parameterized tests (i.e. RowTest, CombinatorialTest) then migrating to Pex should be a piece of cake :)

posted on Friday, May 25, 2007 10:25:02 PM UTC  #    Comments [2]