reportlogo.png Pex - Automated Exploratory Testing for .NET



parameterzedtestsschema.png

  • The result is a small test suite with high code coverage.
  • Pex can be used with Test First or Test After development styles.
  • Pex emits tests and mocks for MSTest, MbUnit, NUnit, xUnit.Net,...
  • Pex integrates with Visual Studio 2008 enabling Exploratory Test Driven Development.
  • Pex builds on top of a managed profiling API, Extended Reflection, which allows to easily build .Net monitoring applications.

More links


Downloads



License

Pex is licensed under the MSR-LA (academic non-commercial use only). Pex samples ships with Msagl  with is licensed under MSR-SSLA.

Universities may obtain source code licenses for academic purposes. Please contact us  for further information.

Getting Started


Welcome to Pex.


More questions?

Papers


Research Papers


  • Pex – White Box Test Generation for .NET link 
    • Nikolai Tillmann, Jonathan de Halleux, Proc. of TAP 2008, the 2nd International Conference on Tests and Proofs, LNCS, vol. 4966, pages 134-153, April 2008.
  • Parameterized Unit Testing with Pex (Tutorial) link 
    • Jonathan de Halleux, Nikolai Tillmann, Proc. of TAP 2008, the 2nd International Conference on Tests and Proofs, LNCS, vol. 4966, pages 171-181, April 2008.
  • DySy: Dynamic Symbolic Execution for Invariant Inference PDF 
    • Christoph Csallner, Nikolai Tillmann, Yannis Smaragdakis, Microsoft Research Technical Report MSR-TR-2007-151, November 2007.
  • Demand-Driven Compositional Symbolic Execution PDF 
    • Saswat Anand, Patrice Godefroid, Nikolai Tillmann, Microsoft Research Technical Report MSR-TR-2007-138, October 2007.
  • Unit Tests Reloaded: Parameterized Unit Testing with Symbolic Execution
    • Nikolai Tillmann, Wolfram Schulte, IEEE Software , vol. 23, no. 4, pp. 38-47, Jul/Aug, 2006.
    • Earlier version as Microsoft Research Technical Report MSR-TR-2005-153 PDF , March 2006.
  • Discovering Likely Method Specifications PDF 
    • Nikolai Tillmann, Feng Chen, Wolfram Schulte, Technical Report MSR-TR-2005-146, March 2006.
  • Mock-object generation with behavior link 
    • Nikolai Tillmann, Wolfram Schulte, Proc. of ASE 2006 , pp. 365-368, 2006.
  • Parameterized Unit Tests PDF 
    • Nikolai Tillmann, Wolfram Schulte, Proc. of FSE/ESEC 2005 . Earlier version as Microsoft Technical Report MSR-TR-2005-64, May 2005.


Other Papers


Frequently Asked Questions


Could you give me a brief comparison between Pex vs MSTest unit testing?

Think about Pex with VSTS unit testing rather than 'vs'. Pex acts as a plugin for unit test framework by providing parameterized unit tests, but it does not prevent the user from writing 'closed' unit tests.

In fact, in many situations, it will probably more adequate to write a 'closed' unit test rather than a parameterized one.

The following example shows how unit tests and parameterized unit tests can live together in the same test class:

  • a classic unit test
    // no parameters, using 'closed' unit tests
    [TestMethod]
    public void AddMoney() {
         Account account = new Account();
         account.Add(100);
         Assert.IsTrue(account.Amount == 100);
    }

  • a parameterized unit test,
    // adding money, we can write a parameterized unit test here
    [PexMethod]
    public void AddMoney(int amount) {
         Account account = new Account();
         account.Add(amount);
         Assert.IsTrue(account.Amount == amount);
    }

Do you support NUnit, MbUnit and xUnit.net?

Yes, extensions for these test frameworks can be downloaded from the Pex Extensions Project.

Can I mix Unit Tests and Parameterized Unit Tests in the same class?

Yes, both can live in the same class. In fact, that is what happends when Pex generates
unit tests.

[TestClass]
class Test {
    [PexMethod] void Foo(int i) {... }
    [TestMethod] void Bar() { ... }
}

Is this a random test generation tool?

No, Pex uses a constraint solver to generate new test inputs.

Is this a test stub generation tool like the MSTest Unit Test Wizard in Visual Studio?

No, from a parameterized unit test written by the user, Pex generates unit tests that call back that test.
In other words, Pex generates test inputs. See example above.

Pex also comes with a Wizard that can generate parameterized test stubs, but they are meant as a boiler
plate starting point, just like the Visual Studio unit test wizard.

Does Pex work with TypeMock?

Currently Pex and TypeMock do not work together.

Do I need to use the PexClassAttribute?

No, the PexClassAttribute is optional. It can be used to specify additional settings for Pex, such as the Test To Code Binding.

Unit Testing


Unit Testing  is a procedure used to validate that individual units of source code are working properly. A unit is the smallest testable part of an application, i.e. a class or method in .Net.

Several frameworks  exist to automate the discovery, execution and result logging of the unit test.

Pex supports a large number of .Net test frameworks.

Parameterized Unit Testing


Parameterized Unit Tests (PUTs) are... tests that take parameters. Unlike traditional unit tests, which are usually closed methods, PUTs take any set of parameters. Is it that simple? Yes! From there, Pex will try to generate the (minimal) set of inputs that fully cover the code reachable from the test.

PUTs are defined using the PexMethod custom attribute in a similar fashion to MSTest (or NUnit, MbUnit, xUnit). PUTs are instance methods logically grouped in classes (tagged with PexClassAttribute). The following sample shows a simple PUT stored in the MyPexTest class:

[PexMethod]
void ReplaceFirstChar(string target, char c) {
    
    string result = StringHelper.ReplaceFirstChar(target, c);
 
    Assert.AreEqual(result[0], c);
}
where ReplaceFirstChar is a method that replaces the first character of a string:

class StringHelper {
    static string ReplaceFirstChar(string target, char c) {
        if (target == null) throw new ArgumentNullException();
        if (target.Length == 0) throw new ArgumentOutOfRangeException();
        return c + target.Substring(1);
    }
}

From this test, Pex can automatically generate inputs for a PUT that cover many execution paths of the tested code. Each input that covers a different execution path gets 'serialized' as a unit test:

[TestMethod, ExpectedException(typeof(ArgumentNullException))]
void ReplaceFirstChar0() {
    this.ReplaceFirstChar(null, 0);
}
...
[TestMethod]
void ReplaceFirstChar10() {
    this.ReplaceFirstChar("a", 'c');
}

For more details on getting started with PUTs, see


See Also

PexMethodAttribute, PexClassAttribute, PexAssume, Generic Parameterized Unit Testing

Automated Exploratory Testing


Classic unit tests are methods without parameters, parameterized unit tests are methods with parameters. In fact, parameterized unit tests have been around for a while now. Referred to as data-driven tests, they were already supported by MSTest in VisualStudio and MbUnit (and previous frameworks) from version 1.

Yet, it used to be the case that the user had to provide the input parameters for those tests, as ranges, spreadsheet or database of some sort. Improper choice of inputs would lead to missed corner cases or a hugely redundant test suite.

With Pex, things change for the better: the user does not have to provide any input to the parameterized unit tests. By analyzing the program behavior at runtime, Pex can generate inputs that matter, i.e. inputs that will increase the coverage of the test suite.

Exploratory Testing


Exploratory Testing is test design and test execution at the same time. As testing progresses, the tester learns more and more about the behavior of the code. Together with experience and creativity he can craft more and better tests.

Pex uses Dynamic Symbolic Execution, a technique that can be seen as an instane of Exploratory Testing. The tool executes the code multiple times and learns about the program behavior by monitoring the control and data flow. After each run, it picks a branch that was not covered previously, builds a constraint system (i.e. predicate over the test inputs) to reach that branch, then uses a constraint solver to come up with new test inputs, if any. The test is executed again with the new inputs, and this process repeats. On each run, Pex might discover new code and dig deeper into the implementation. In this way, Pex explores the behavior of the code. We also refer to this process as Automated Exploratory Testing.

Input Generation By Dynamic Symbolic Execution


Pex generates inputs for parameterized unit tests using a feedback loop. It refines a predicate q: I -> {true, false} over the formal test input parameters I. q represents the set of behaviors which Pex has already observed. Initially, q := false, since nothing has been observed yet.

The steps of the loop:
  1. Pex determines inputs i such that q(i)=false using a constraint solver. By construction, the input i will take an execution path that we have not seen before. (And initially, this means i can by any input since we haven't seen any execution path yet.)
  2. Pex executes the test with the chosen input i, and monitors the execution of the test and the program-under-test takes.
  3. During the execution, the program takes a particular path which is determined by all the conditional branches of the program. The set of all conditions that determine the execution is called the path condition, written as the predicate p: I -> {true, false} over the formal input parameters. Pex computes a representation of this predicate.
  4. Set q := (q or p), i.e. we record that we have now seen the path represented by p.
  5. Go to 1.

Pex' constraint solver can deal with values of all types that may appear in .Net programs:

Pex filters out those inputs which violate stated assumptions.

Besides the immediate inputs (arguments to parameterized unit tests), a test can draw further input values from the PexChoose static class. The choices also determines the behavior of mocks.

Code Coverage Analysis


Code coverage is collected by on-the-fly code instrumentation. (No static instrumentation and resigning of assemblies is required as is when using Magellan. For more information about the implementation, see here.) The collected information contains details information about the frequency of all explicit and implicit branching decisions. From that, edge and basic block coverage information is computed, and basic block coverage is visualized on the source files.

Pex uses an iterative test input generation algorithm which systematically enumerates all reachable execution paths of a program.

Supported Test Frameworks


Pex supports the following test frameworks:


Attribute Usage Table

Feature with VSTS Description
fixture [TestClass, PexClass] tests are logically grouped in a type
parameterized test [PexMethod] instance method tagged with PexMethod
fixture setup [ClassInitialize] supported
fixture teardown [ClassCleanup] supported
test setup [TestInitialize] supported
test teardown [ClassCleanup] supported

All other attributes are copied to the generated unit tests but their function is not understood.

  • For VSTS, the ITestContext instance is always null.

Specifying up the test framework

Pex automatically guesses the test framework by walking the list of assembly references of the test project and looking for the unit test framework assembly. If Pex cannot guess the test framework you are using, you can set it with the TestFramework option of the PexAssemblySettingsAttribute.

[assembly: PexAssemblySettings(TestFramework = "Repro")]

Microsoft.ExtendedReflection


Extended Reflection (ER) is a library that offers functionality that greatly extends the standard reflection library, and also lifts the unmanaged CLR profiling API into the managed world.

ExtendedReflection.png

Our Presentations and Screencasts contain an overview of how the managed profiling API works and how you can use it.

Extended Reflection consists of two assemblies:

  • The managed assembly has the following namespaces:
    • Metadata -- metadata model that can faithfully represent all entities that exist at runtime
    • DataAccess -- fast and type-safe accessors to "live" program data
    • Interpretation -- interpreter of all MSIL instructions, and symbolic representation of runtime values and entire states by terms
    • Reasoning -- interface for symbolic reasoning over MSIL instructions
    • Monitoring -- the managed counterpart of the ClrMonitor that receives callbacks from the instrumented code
    • Utilities -- a set of general utility classes (collections, for debugging, logging, etc)
  • The unmanaged CLR profiler called "ClrMonitor"; it instruments MSIL instructions, i.e. redirecting calls and inserting callbacks

Extended Reflection comes with a set of Code Substitutions to better handle calls to native code.

Reference Manual


Reference

WikiBook


This manual was rendered as a single HTML page at

Samples


Pex comes with a set of samples that you can open them from the program folder.

Requirements

  • Visual Studio 2008 Professional or higher,
    • Visual C#,
  • you can force the installation of the samples by using the 'Custom' selection of features in the installer.

Contents

If you want guidance at which sample is the right one for you to start, read here.


More Samples


The Pex Extensions Project contains additional extensions and samples:

  • DySy, advanced extensiblity sample

Screencasts


Requirements


  • Windows Vista 32bit
    • Other versions of Windows should work but are untested
    • x64 support is under development (available only inside of Microsoft)
  • .NET Framework 2.0
    • also supported .NET Framework 3.0 and 3.5

While not required, we suggest Visual Studio 2008 Professional (or better). Pex comes with an AddIn for Visual Studio.

Samples Requirements

  • Visual Studio 2008 Professional
    • Requires Visual C# and MSTest
    • Check in Visual Studio in the Help - About Microsoft Visual Studio dialog.

Go to the Downloads

Pex Extensions Project


Pex is extensible! Many extension points are available to plugin into the Pex infrastructure. For example, you can build
  • custom test framework support,
  • custom language support,
  • custom exception filtering,
  • custom symbolic checking,
  • or even directly 'listening' to the instrumentation events.

Pex Extensions is an open source project that centralizes extensions for Pex. If you want to build a new extension (as open source), we would recommend you to join that project and develop it over there.


Support for NUnit, MbUnit or xUnit.net is provided through this project.

See Also

Community 

Tutorial


pextutorial.png

The Pex tutorial will help you get started with Pex in Visual Studio, and it explains the how Pex works.

License


Microsoft Research License Agreement
Non-Commercial Use Only
Pex

_______________________________________________________

This Microsoft Research License Agreement, including all exhibits ("MSR-LA") is a legal agreement between you and Microsoft Corporation (“Microsoft” or “we”) for the software or data identified above, which may include source code, and any associated materials, text or speech files, associated media and "online" or electronic documentation and any updates we provide in our discretion (together, the "Software").

By installing, copying, or otherwise using this Software, found at http://research.microsoft.com/downloads, you agree to be bound by the terms of this MSR-LA. If you do not agree, do not install copy or use the Software. The Software is protected by copyright and other intellectual property laws and is licensed, not sold.

SCOPE OF RIGHTS:
You may use, copy, reproduce, and distribute this Software for any non-commercial purpose, subject to the restrictions in this MSR-LA. Some purposes which can be non-commercial are teaching, academic research, public demonstrations and personal experimentation. You may also distribute this Software with books or other teaching materials, or publish the Software on websites, that are intended to teach the use of the Software for academic or other non-commercial purposes.
You may not use or distribute this Software or any derivative works in any form for commercial purposes. Examples of commercial purposes would be running business operations, licensing, leasing, or selling the Software, distributing the Software for use with commercial products, using the Software in the creation or use of commercial products or any other activity which purpose is to procure a commercial gain to you or others.
If the Software includes source code or data, you may create derivative works of such portions of the Software and distribute the modified Software for non-commercial purposes, as provided herein.
If you distribute the Software or any derivative works of the Software, you will distribute them under the same terms and conditions as in this license, and you will not grant other rights to the Software or derivative works that are different from those provided by this MSR-LA.
If you have created derivative works of the Software, and distribute such derivative works, you will cause the modified files to carry prominent notices so that recipients know that they are not receiving the original Software. Such notices must state: (i) that you have changed the Software; and (ii) the date of any changes.

In return, we simply require that you agree:
1. That you will not remove any copyright or other notices from the Software.
2. That if any of the Software is in binary format, you will not attempt to modify such portions of the Software, or to reverse engineer or decompile them, except and only to the extent authorized by applicable law.
3. That Microsoft is granted back, without any restrictions or limitations, a non-exclusive, perpetual, irrevocable, royalty-free, assignable and sub-licensable license, to reproduce, publicly perform or display, install, use, modify, post, distribute, make and have made, sell and transfer your modifications to and/or derivative works of the Software source code or data, for any purpose.
4. That any feedback about the Software provided by you to us is voluntarily given, and Microsoft shall be free to use the feedback as it sees fit without obligation or restriction of any kind, even if the feedback is designated by you as confidential.
5. THAT THE SOFTWARE COMES "AS IS", WITH NO WARRANTIES. THIS MEANS NO EXPRESS, IMPLIED OR STATUTORY WARRANTY, INCLUDING WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ANY WARRANTY AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE SOFTWARE OR ANY WARRANTY OF TITLE OR NON-INFRINGEMENT. THERE IS NO WARRANTY THAT THIS SOFTWARE WILL FULFILL ANY OF YOUR PARTICULAR PURPOSES OR NEEDS. ALSO, YOU MUST PASS THIS DISCLAIMER ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS.
6. THAT NEITHER MICROSOFT NOR ANY CONTRIBUTOR TO THE SOFTWARE WILL BE LIABLE FOR ANY DAMAGES RELATED TO THE SOFTWARE OR THIS MSR-LA, INCLUDING DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL OR INCIDENTAL DAMAGES, TO THE MAXIMUM EXTENT THE LAW PERMITS, NO MATTER WHAT LEGAL THEORY IT IS BASED ON. ALSO, YOU MUST PASS THIS LIMITATION OF LIABILITY ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS.
7. That we have no duty of reasonable care or lack of negligence, and we are not obligated to (and will not) provide technical support for the Software.
8. That if you breach this MSR-LA or if you sue anyone over patents that you think may apply to or read on the Software or anyone's use of the Software, this MSR-LA (and your license and rights obtained herein) terminate automatically. Upon any such termination, you shall destroy all of your copies of the Software immediately. Sections 3, 4, 5, 6, 7, 8, 11 and 12 of this MSR-LA shall survive any termination of this MSR-LA.
9. That the patent rights, if any, granted to you in this MSR-LA only apply to the Software, not to any derivative works you make.
10. That the Software may be subject to U.S. export jurisdiction at the time it is licensed to you, and it may be subject to additional export or import laws in other places. You agree to comply with all such laws and regulations that may apply to the Software after delivery of the software to you.
11. That all rights not expressly granted to you in this MSR-LA are reserved.
12. That this MSR-LA shall be construed and controlled by the laws of the State of Washington, USA, without regard to conflicts of law. If any provision of this MSR-LA shall be deemed unenforceable or contrary to law, the rest of this MSR-LA shall remain in full effect and interpreted in an enforceable manner that most nearly captures the intent of the original language.

Copyright (c) Microsoft Corporation. All rights reserved.


Revised September 15, 2006


_______________________________________________________
Microsoft Automatic Graph Layout 2007

This Microsoft Research Shared Source license agreement ("MSR-SSLA") is a legal agreement between you and Microsoft Corporation ("Microsoft" or "we") for the software or data identified above, which may include source code, and any associated materials, text or speech files, associated media and "online" or electronic documentation and any updates we provide in our discretion (together, the "Software").

By installing this software you agree to these terms. If you do not agree, do not install, copy or use the Software. The Software is protected by copyright and other intellectual property laws and is licensed, not sold.

SCOPE OF RIGHTS:
You may use, copy, reproduce, and distribute this Software for any non-commercial purpose, subject to the restrictions in this MSR-SSLA. Some purposes which can be non-commercial are teaching, academic research, public demonstrations and personal experimentation. You may also distribute this Software with books or other teaching materials, or publish the Software on websites, that are intended to teach the use of the Software for academic or other non-commercial purposes.
You may not use or distribute this Software or any derivative works in any form for commercial purposes. Examples of commercial purposes would be running business operations, licensing, leasing, or selling the Software, distributing the Software for use with commercial products, using the Software in the creation or use of commercial products or any other activity which purpose is to procure a commercial gain to you or others.
If the Software includes source code or data, you may create derivative works of such portions of the Software and distribute the modified Software for non-commercial purposes, as provided herein.

In return, we simply require that you agree:
1. That you will not remove any copyright or other notices from the Software.
2. That if any of the Software is in binary format, you will not attempt to modify such portions of the Software, or to reverse engineer or decompile them, except and only to the extent authorized by applicable law.
3. That if you distribute the Software or any derivative works of the Software, you will distribute them under the same terms and conditions as in this license, and you will not grant other rights to the Software or derivative works that are different from those provided by this MSR-SSLA.
4. That if you have created derivative works of the Software, and distribute such derivative works, you will cause the modified files to carry prominent notices so that recipients know that they are not receiving the original Software. Such notices must state: (i) that you have changed the Software; and (ii) the date of any changes.
5. That Microsoft is granted back, without any restrictions or limitations, a non-exclusive, perpetual, irrevocable, royalty-free, assignable and sub-licensable license, to reproduce, publicly perform or display, install, use, modify, distribute, make and have made, sell and transfer your modifications to and/or derivative works of the Software source code or data, for any purpose.
6. That any feedback about the Software provided by you to us is voluntarily given, and Microsoft shall be free to use the feedback as it sees fit without obligation or restriction of any kind, even if the feedback is designated by you as confidential.
7. THAT THE SOFTWARE COMES "AS IS", WITH NO WARRANTIES. THIS MEANS NO EXPRESS, IMPLIED OR STATUTORY WARRANTY, INCLUDING WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ANY WARRANTY AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE SOFTWARE OR ANY WARRANTY OF TITLE OR NON-INFRINGEMENT. THERE IS NO WARRANTY THAT THIS SOFTWARE WILL FULFILL ANY OF YOUR PARTICULAR PURPOSES OR NEEDS. ALSO, YOU MUST PASS THIS DISCLAIMER ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS.
8. THAT NEITHER MICROSOFT NOR ANY CONTRIBUTOR TO THE SOFTWARE WILL BE LIABLE FOR ANY DAMAGES RELATED TO THE SOFTWARE OR THIS MSR-SSLA, INCLUDING DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL OR INCIDENTAL DAMAGES, TO THE MAXIMUM EXTENT THE LAW PERMITS, NO MATTER WHAT LEGAL THEORY IT IS BASED ON. ALSO, YOU MUST PASS THIS LIMITATION OF LIABILITY ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS.
9. That we have no duty of reasonable care or lack of negligence, and we are not obligated to (and will not) provide technical support for the Software.
10. That if you breach this MSR-SSLA or if you sue anyone over patents that you think may apply to or read on the Software or anyone's use of the Software, this MSR-SSLA (and your license and rights obtained herein) terminate automatically. Upon any such termination, you shall destroy all of your copies of the Software immediately. Sections 5, 6, 7, 8, 9, 10, 13 and 14 of this MSR-SSLA shall survive any termination of this MSR-SSLA.
11. That the patent rights, if any, granted to you in this MSR-SSLA only apply to the Software, not to any derivative works you make.
12. That the Software may be subject to U.S. export jurisdiction at the time it is licensed to you, and it may be subject to additional export or import laws in other places. You agree to comply with all such laws and regulations that may apply to the Software after delivery of the software to you.
13. That all rights not expressly granted to you in this MSR-SSLA are reserved.
14. That this MSR-SSLA shall be construed and controlled by the laws of the State of Washington, USA, without regard to conflicts of law. If any provision of this MSR-SSLA shall be deemed unenforceable or contrary to law, the rest of this MSR-SSLA shall remain in full effect and interpreted in an enforceable manner that most nearly captures the intent of the original language.


Copyright (c) Microsoft Corporation. All rights reserved.




Introduction


Pex generates Unit Tests from hand-written Parameterized Unit Tests through Automated Exploratory Testing based on Input Generation:


All tools work on top of Pex' managed profiling API, Extended Reflection, which allows to easily build .Net monitoring applications. The managed profiling API is built on top of the CLR Profiling API.

How Pex Will Help You


If you want to ...



Writing Parameterized Unit Tests


When you are ready to write your own parameterized unit tests, we will show you how depending on the code you want to test:

  • Algorithms over primitive data, arrays of primitive data
    • Write parameterized unit tests. more...
  • Algorithms over interfaces
    • Use Pex' automatic mock object generation. more...
  • Algorithms over complex data, e.g. compiler
    • Let Pex generate an abstract representation of the data first, then feed it to the algorithm. more...
    • Let Pex build instances via custom object creation and data invariants, then invoke algorithm. more...
  • Data containers
    • Write parameterized unit tests. more...
    • Let Pex build instances via custom object creation and data invariants, then invoke a method of the container, and check invariants afterwards again. more...
    • Write parameterized unit tests which call different methods of the implementation depending on the parameter values. more...
  • Client / Server Architectures in a public environment, e.g. web service client, web service server
    • Generate interfaces for web services. more...
    • Use Pex' mock objects to simulate other side. more...

Cheat Page

important attributes in Pex: Print this page!

Getting Started

Add Pex reference Microsoft.Pex.Framework.dll
Bind test project [assembly: PexAssemblyUnderTest("UnderTest")]

Custom Attributes

PexClassAttribute marks a type containing PUT
PexMethodAttribute marks a PUT
PexAssumeNotNullAttribute marks a non-null parameter

using Microsoft.Pex.Framework;
[..., PexClass(typeof(Foo))]
public partial class FooTest {
    [PexMethod]
    public void Bar([PexAssumeNotNull]Foo target, int i) {
        target.Bar(i);
    

Static Helpers

PexAssume evaluates assumptions (input filtering)
PexAssert evaluates assertions
PexChoose generates new choices (additional inputs)
PexStore logs live values to the report and/or generated tests

[PexMethod]
void StaticHelpers(Foo target){
    PexAssume.IsNotNull(target);
    int i = PexChoose.FromCall(this).Value<int>("i");
    string result = target.Bar(i);
    PexStore.Add("result", result);
    PexAssert.IsNotNull(result);

Instrumentation

PexAssemblyUnderTestAttribute binds a test project to a project
PexInstrumentAssemblyAttribute specifies to instrument an assembly

[assembly: PexAssemblyUnderTest("MyAssembly")] // also instruments "MyAssembly"
[assembly: PexInstrumentAssembly("Lib")]

Public Issue Tracker


This is a snapshot of our current issues. If you found a new issue or feature request, use our mailing list to post it.

Issues


ID Title Update Date
1942 Active.gif [external] Support for TypeMock 12/9/2007 11:48:29 PM
2032 Active.gif [external] Wizard extensibility 1/5/2008 2:47:46 AM
2047 Active.gif [external] Add a Raise method for events 1/8/2008 3:54:14 AM
2239 Proposed.gif [external] inserting methods in opened .g. files corrupts them 2/5/2008 11:26:37 AM
2036 Proposed.gif [external] generating test stubs does not update project references 1/7/2008 12:20:46 PM
2031 Closed.gif [external] Wizard should generate set/get/assert systematically 1/8/2008 2:40:18 AM
2237 Closed.gif [external] Add Assert.Inconclusive on generated tests 3/20/2008 8:38:55 AM
2238 Closed.gif [external] Method that returns bool should have a branch 2/14/2008 5:25:19 PM

MSTest


Visual Studio Unit Test Framework

Pex can leverage already existing test suites, and can generate tests for MSTest.
Z3

Theorem Prover and Constraint Solver.

See http://research.microsoft.com/projects/Z3 .

PexClassAttribute


Attribute that marks a class that contains 'explorations'. It is the equivalent of MSTest's TestClassAttribute (or NUnit's TestFixtureAttribute). This attribute is optional.

The classes marked with PexClass must be 'default constructible':
  • publicly exported type,
  • default constructor
  • not abstract

If the class does not meet those requirements, an error will be proced in the report and the exploration will fail.

It is also strongly advised to make those classes 'partial' so that Pex can generate new tests that are part of the class, but in a separate file. This approach solves a lot of problems due to visibility and fits naturally into C#.

This attribute inherits from the PexSettingsAttributeBase and contains a lot of customization parameters.

  • additional suite and categories,
[TestClass] // VSTS test fixture attribute
[PexClass(Suite = "checkin")] // Pex fixture attribute
public partial class MyTests { ... }
[PexClass(typeof(Foo))] // this is a test for Foo
public partial class FooTest { ... }

The class may contain methods annotated with the PexMethod. Pex also understands SetUp and TearDown methods.


See Also

Settings Waterfall, PexMethodAttribute

Test To Code Binding


Pex lets specify the code under test for a particular assembly or fixture, i.e. the test to code binding.

This information is very interesting in many aspects:

  • for you,
    • it expresses explicitly the intent of the developer/tester,
    • it can be used through the command line to filter tests to run,
  • for Pex,
    • focus it's search on the code under test,
    • instrument the code under test,
    • tell the wizard where to add generated files,
    • provide coverage numbers with respect to the code under test,
  • for other tools
    • e.g. which tests to rerun after code has changed.

Assembly Under Test

The PexAssemblyUnderTest attribute can be used to specify that an assembly MyAssembly is tested by the current test project:

[assembly: PexAssemblyUnderTest("MyAssembly")]

Type Under Test


The type under test for a given fixture can be set through one of the PexClass constructors:

[TestClass, PexClass(typeof(Foo))]
public partial class FooTestClass
{ ... 


[assembly: PexAllowedExceptionFromTypeUnderTest(typeof(ArgumentException))]

Coverage


As a side effect of the runtime monitoring, Pex computes collects dynamic code coverage data. We call it dynamic because Pex knows only about code that has been executed, therefore it cannot give absolute values for coverage such as other coverage tool usually do.

Coverage Domains


Pex partitions code into the following coverage domains: user code under test, user or test code or system code.
  • user code under test: this is the code under test for the current exploration. This code is included in the computation of the coverage numbers (block counts, etc...) and the source coverage will be rendered in the reports. Usually, this is the product code.
  • user or test code: this is code that is part of your projects or tests but that is not tested by the current exploration. This code is not included in the computation of the coverage numbers but the source coverage is still rendered in the reports (with different colors). Usually, this is the test code since you don't care about your test coverage but yet it is interresting to see the coverage of tests.
  • system code: any framework or third code for which you do not want to collect coverage data. This code is not included in the coverage numbers and source coloring.

To change the defaults, use attributes deriving from PexCoverageFilterAttributeBase or the Type Under Test feature.

Coverage Units


These are the different ways that Pex uses to characterize coverage:
  • blocks, basic blocks,
  • method touched, the number of methods that were touched at all.

Sample


Let's consider the following simple exploration (without any parameter), to illustrate the coverage reports:

    class SystemCode {
        public void Run() {
            Console.WriteLine("I should show NOT show up!");
        }
    }
    class UserOrTestCode {
        public void Run() {
            bool b = true;
            if (b)
                Console.WriteLine("I should show up blue!");
            else
                Console.WriteLine("I should show up gray!");
        }
    }
    class UserCodeUnderTest {
        public void Run() {
            bool b = true;
            if (b)
                Console.WriteLine("I should show up green!");
            else
                Console.WriteLine("I should show up red!");
        }
    }
    [TestClass]
    [PexClass(
        // type under test is in UserCodeUnderTest domain
        typeof(UserCodeUnderTest), 
        Suite = "checkin")]
    // UserOrTestCode is the default domain
    // [PexCoverageFilterType(PexCoverageDomain.UserOrTestCode, typeof(UserOrTestCode))]
    [PexCoverageFilterType(PexCoverageDomain.SystemCode, typeof(SystemCode))]
    public partial class CoverageFilterTest {
        [PexMethod]
        public void CallExcludeMe()
        {
            new UserCodeUnderTest().Run();
            new UserOrTestCode().Run();
            new SystemCode().Run();
        }
    }

The resulting coverage is as follows:

coveragecolors.png

See Also

PexCoverageFilterTypeAttribute, TestClassAttribute, PexClassAttribute, PexMethodAttribute

PexMethodAttribute


This attribute marks a method as a parameterized unit test. The method must reside inside a class marked with PexClass attribute.

Pex will generate traditional, parameterless tests, which call the parameterized unit test with different parameters.

The parameterized unit test
  • must be an instance method,
  • must be visible to the test class into which the generated tests are placed according to the Settings Waterfall,
  • may take any number of parameters,
  • may be generic.

Example

[PexClass]
public partial class MyTests {
     [PexMethod]
     public void MyTest(int i)
     { ... }
}

This attribute inherits from the PexSettingsAttributeBase and contains may named parameters for customization.

See Also

PexClassAttribute, Settings Waterfall, Generic Parameterized Unit Testing

The "Hello World" of Pex


Since Pex finds inputs relevant to the tested program, we can use Pex to generate the famous Hello World! string. We assume that you have created a C# MSTest Test Project and added a reference to Microsoft.Pex.Framework. If you are using another test framework, create a C# class library and refer to the test framework documentation on how to set up the project.

The example below creates a couple of constraints on the parameter called value so that Pex will generate the desired string.

using System;
using Microsoft.Pex.Framework; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
 
[TestClass]
public partial class HelloWorldTest {
    [PexMethod]
    public void HelloWorld([PexAssumeNotNull]string value) {
        if (value.StartsWith("Hello")
            && value.EndsWith("World!")
            && value.Contains(" "))
            throw new Exception("found it!");
    }
}

Once compiled and executed, Pex generates a set of tests such as the following:

Test Numbervalue
1""
2"\0\0\0\0\0\0"
3"Hellol"
4"HellolWorld!"
5"Hello World!"

We have a winner. In fact, the generated tests code should include a test like the following:

[TestMethod()]
[PexRaisedException(typeof(Exception))]
public void HelloWorld05()
{
    this.HelloWorld("Hello World!");
}

See Also

TestClassAttribute, PexClassAttribute, PexMethodAttribute

Assumptions and Assertions


Users can use assumptions and assertions to express preconditions (assumptions) and postconditions (assertions) about their tests. When Pex generates a set of parameter values and 'explores' the code, it might violate an assumption of the test. When that happens, Pex will not generate a test for that path but silently ignore it.

Assertions are a well known concept in regular unit test framework, so Pex already 'understands' the built-in Assert classes provided by each supported test framework. However, most framework do not provide an Assume class. In that case, Pex provides the PexAssume class. If you do not want to use an existing test framework, Pex also has the PexAssert class.

[PexMethod]
public void Test1(object o) {
    // precondition: o should not be null
    PexAssume.IsNotNull(o);
 
    ...
}

In particular, the non-nullness assumption can be encoded as custom attribute:

[PexMethod]
public void Test2([PexAssumeNotNull] object o)
// precondition: o should not be null
{
   ...
}

See Also

PexClassAttribute, PexMethodAttribute, PexAssumeNotNullAttribute

Generic Parameterized Unit Tests


Parameterized unit tests can be generic methods. In that case, the user has to specify the types used to instantiate the method using the PexGenericArguments attribute.

[PexClass]
public partial class ListTest {
    [PexMethod]
    [PexGenericArguments(typeof(int))]
    [PexGenericArguments(typeof(object))]
    public void AddItem<T>(List<T> list, T value)
    { ... }
}

See Also
PexMethodAttribute

Attribute Glossary


By Namespaces



Inheritance Tree


PexAssume


Static class to express assumptions, i.e. a precondition, in parameterized unit tests. The methods of this class can be used to filter out undesirable test inputs.

If the assumed condition does not hold for some test input, a PexAssumeFailedException is thrown, which will cause the test to be silently ignored.

Example

The following parameterized test will not consider j=0.

public void TestSomething(int i, int j) {
     PexAssume.AreNotEqual(j, 0);
     int k = i/j;
     ...
}

Remarks


The code above is almost equivalent to
     if (j==0)
          return;
except that a failing PexAssume results in no test cases, whereas in the case of an if-statement, Pex would generate a separate test case to cover the then-branch of the if-statement.

PexAssume also contains specialzed nested classes for assumptions on string, arrays and collections.

See Also


PexAssert, PexSymbolicValue

MbUnit


Open Source Test Framework: http://www.mbunit.com 

Pex can leverage already existing test suites, and can generate tests for MbUnit.

Test Inputs


Pex generates test inputs.

Inputs to a test come from various sources:
Constraint Solver

Pex uses a constraint solver to determine what the relevant input values of a test and the program-under-test are.

Pex uses Z3 as a constraint solver.

Path Condition


During Input Generation, Pex runs a parameterized unit test multiple times to determine relevant test inputs. For each run, Pex computes the abstract condition over the inputs that characterizes the execution path the program takes. This abstraction condition is called the path condition. It is a boolean expression which may refer to the test inputs.

For example, for the method
  [PexMethod]
  public void Test(int i) 
  {
      if (i>0) 
          Console.WriteLine("positive");
  }
Pex will try to test inputs, which might be:
  • Test(-1), which can be characterized by the condition i<=0, and
  • Test(0), which can be characterized by the condition i>0.

Together, these two exemplary test inputs are representative for all different behaviors of the called method.

When you look at a test report, you have the option to view the path condition
PathCondition0.png

When you expand the [+], you see a code snippet, which represents a boolean-valued expression that involves the parameter names of the parameterized test.
PathCondition1.png

Pex simplifies and rearranges the conditions internally; here, you can see that instead of i<=0 Pex represented the condition as 0>=i.
Also, the code shown for the path condition might not be executable as is, or look suboptimal.

Generating Integers and Floats


Pex' constraint solver determines test input values of primitives types such as byte, int, float, ... in order to trigger different execution paths of the test and the program-under-test.

For integers, the constraint solver can reason about all arithmetic operations, treating integers as 32-bit or 64-bit values. Bitwise manipulations are supported as well.

For floating point number, the constriant solver approximates the behavior of linear arithmetic with rational numbers.

Enums are treated similar to their underlying integer type.

Generating Objects


Pex can either create instances of existing .Net classes, or you can use Pex to automatically create mock objects that implement a given interface and behave in different ways depending on its usages.


When Pex generates test inputs, it imposes certain bounds on the size of the inputs. Pex only considers a set of types when trying to build values which are assignable to the test parameters.

Generating Structs


Pex reasoning about struct-values is similar to how it deals with objects.

Arrays, Strings


Pex monitors the executed instructions when it runs a test and the program-under-test. In particular, it observes when the program depends on the length of a string or an array (and the lower bounds and lengths of a multi-dimensional array). It also observes how the program uses the different elements of a string or array. It then uses a constraint solver to determine which lengths and element values might cause the test and the program-under-test to behave in interesting ways.

Pex tries to minimize the size of the arrays and strings needed to trigger interesting program behaviors.

PexChoose


Static class which supplies auxiliary input values to a test, as well as the choices which determine the behavior of mocks.

(This oracle does not decide whether a test passes for particular input values, it simply provides input values. It is still up to the user to restrict the input values, and to write assertions to define when a test passes or fails.)

Modes of operation


The PexChoose class can operate in two modes:
  • While Pex is performing a symbolic analysis of the test and the tested code during Input Generation, the chooser returns arbitrary values, and Pex tracks how the value is used in the test and the tested code. Pex will generate relevant values to trigger different execution paths in the test and the tested code.
  • The generated code for particular test cases sets up the oracle in a specific way, so that the reexecution of such a test case will make particular choices to trigger a particular execution path.

Usage


  • If you want to use the oracle to determine the behavior of a method (e.g. of a mock object), you can call PexChooser.FromCall, which returns a chooser.
public int Foo() {
    var call = PexChoose.FromCall(this);
    return call.Result<int>();
}
  • If you want to draw an auxiliary input value (or a sequence of auxiliar input values), you can call PexChoose.CreateSession, which returns a choice session.
    • You can use the static PexChoose.DefaultSession if a single static session works for you.
public void Test() {
    ArrayList list = new ArrayList();
    while(PexChoose.DefaultSession.Value<bool>("next"))
        list.Add(null);
    ...
}


See Also

Mocks, IPexChoiceSession

Mocks


How to test a method which has a parameter of an interface type? Or of a non-sealed class? We don't know which implementations will later be used when this method is called! And maybe we don't even have any real implementation available at test time.

The conventional answer: mock objects with explicit behavior

A mock object implements an interface (or extends a non-sealed class). It does not represent a real implementation, but just a shortcut that allows the execution of tests using the mock object. It's behavior is manually written as part of the each test case where it is used. Many tools exist which make it easier to write such mock objects and their expected behavior. But it must still be written by hand.

Generated mock objects with generated behavior

Instead of manually writing the expected behavior of a mock object for each individual test case, Pex can generate relevant behavior:

Choose and Replay

Pex mocks have two different execution modes:

  • choosing, when exploring code, Pex mocks are a source of additional test inputs, and Pex will try its best to choose interesting values,
  • replay, when executing a previously generated test, Pex mocks behave like stubs with behavior (i.e. predefined behavior).

Pex comes with a wizard that can automatically generate those mocks.

Example

Let's illustrate this with a simple mock of a toy interface INamed:

interface INamed {
    string GetName();
}

Writing the mock

The mock for this interface looks as follows:

class MNamed : INamed {
    public string GetName() {
        var call = PexChoose.FromCall(this);
        return call.Result<string>();
    }
}

So what did we do really... The mock implementation of GetName fetches a oracle (i.e. an interface from which new values can be queried).

    var call = PexChoose.FromCall(this);

The oracle can be used to choose new values. It's like adding parameters to the test, but not through the signature. In this case, we ask Pex to get a new result value.

    return call.Result<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 'Marc'. Notice that the test was also tagged with the PexUseType to tell Pex that the MNamed type can be used, which will be needed to get a INamed instance.

[PexMethod]
public void GetName() {
    var name = new MName();
    if (name.GetName() == "Marc")
        Console.WriteLine("hello marc");
}

Generated tests

Pex generates 2 unit tests that cover that method.

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

// test 2
MockTest.MNamed mn0 = new MockTest.MNamed();
var chooser = PexChoose.NewTest();
chooser.OnCall(0, "MNamed.GetName()")
      .Returns("Marc");
this.GetName();

The chooser 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,
choose.OnCall(0, "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:

class MNamed : INamed {
    private string name;
    public string GetName() {
        if(this.name == null)
            this.name = PexChoose.FromCall(this).ValueNotNull<string>("name");
        return this.name;
    }
}

Note that we no longer choose a result value, but make a named choice (with the name 'name'). It doesn't matter much to Pex, it just changes the generated code that sets up the mock objects.

More on mocks

The following topics discuss how to mock particular elements:


See Also

Martin Fowler's Mocks Aren't Stubs , AppendFormat.

In this mode, Pex emits a new file and entry point for each test. It duplicates all the necessary attributes so that there is no dependency on Microsoft.Pex.Framework.

NUnit


Open Source Test Framework: http://www.nunit.org 

Pex can leverage already existing test suites, and can generate tests for NUnit.

xUnit.Net


Unit test framework

TestFramework


Option of the PexAssemblySettingsAttribute to specify the test framework to be used. Values for this parameter are built dynamically, please consult command line help.

See Also
Supported Test Frameworks

PexAssemblySettingsAttribute


This attribute can be set at the assembly level to override default settings value for all explorations. It inherits from the PexSettingsAttributeBase.

using Microsoft.Pex.Framework;
// overriding the test framework selection
[assembly: PexAssemblySettings(TestFramework = "Naked")]

Options specific to this attribute:

See Also

Settings Waterfall
This namespace contains a meta data model of the CLR. Parts of it are quite similar to the standard reflection library, but it goes further in many ways:

  • It describes the type system from the point of view of the execution engine, which includes explicit box types and information about memory layouts
  • It decodes the instruction stream, and provides a sequence of instructions as well as a basic-block representation
  • It decodes signature blobs
  • It can perform operations which are normally hidden by the execution engine, e.g. vtable-lookups
  • It includes facilities to create types which can be used to instantiate generic types whose type parameters have constraints
  • It aggressively caches data, and works around some quirks in the standard reflection implementation
  • In the following, the core concepts of the library are presented in more detail.

In order to reflect over instruction sequences, it also contains the concepts:

This namespace contains various utilities for fast and type-safe access to "live" program data without the overhead of boxing that is normally incurred when using standard reflection for this purpose. (Basically, it generates specialized code with Reflection.Emit for all types.)
This namespace contains an abstract model of the data-manipulating operations of the CLR, where all values are tracked as terms.

Concepts:



This namespace also contains visitors and pretty-printers for terms.
The Microsoft-branded version of CIL.
This namespace defines the notion of a formula, and the concept of a solver.
This namespace contains the Monitoring.Controller, which can be used to start and stop the monitoring callbacks, and to setup a process for monitoring.

This module also contains some other internal concepts:
  • Static callbacks which delegate to a user-provided Execution Monitor.
  • Substitutions which emulate the behavior of method calls but drive a user-provided Execution Monitor in addition.
Since all standard assemblies like mscorlib and System may be instrumented, interesting situations arise when the monitoring callbacks perform rather simple operations which in turn lead to calls into mscorlib or System.
Fortunately, Microsoft.ExtendedReflection provides a shield which deals with such re-entrance problems.

Still, this shield comes with a performance overhead.

The utilities of Microsoft.ExtendedReflection provide alternatives to methods of the standard libraries (just as the extended metadata is an alternative to the standard reflection library).

In particular:
  • Utilities.Safe.Collections contains a set of collection types which are safe from instrumentation (and therefore faster). This set of types include many commonly desired collection types which cannot be found in the standard System.Collections.Generic namespace.
  • Utilities.Safe.Diagnostics provide alternatives to the Debug and Debugger class of the standard System.Diagnostics namespace.

Overview


The ClrMonitor is an unmanaged COM component that implements the CLR profiling API. It uses this API mainly to rewrite MSIL instructions of selected methods, types or assemblies on-the-fly at JIT time. It can redirect calls and insert callbacks in the MSIL instruction sequence, enabling the observation of the execution of the program at a fine grained level:

  • (Static) calls can be redirected. The redirection target may call the original call target.
  • Similar to the standard CLR profiling API, the ClrMonitor monitors when a method is entered or exited.
  • It also monitors the concrete parameter values that are passed to a monitored method.
  • The execution of every instruction can be monitored.
  • The control flow is monitored, i.e. the evaluation of all explicit conditional branches, and of all implicit checks that can cause exceptions.
  • Every monitored event causes a callback into the core Microsoft.ExtendedReflection assembly, which can dispatch the callbacks to a user-provided Execution Monitor.

Code instrumentation


The instruction sequence of each instrumented method is rewritten. It starts by inserted instructions which check whether monitoring is currently on. If not, the original instructions are executed. It if it turned on, the instrumented version of the instructions is execution, starting with a callback to EnterMethod(m, c), and eventually finished by a callback to LeaveMethod(m), where m identifies the current method, and c is the number of branch identifiers that the instrumented code will refer to within the method body.

EnterMethod returns a Boolean value that indicates whether the monitor is interested in the concrete arguments to the method. If it returns true, a sequence of calls to Argument<T>(i, v), ArgumentPtr(i, v, t), ArgumentTypedReference(i, v) and ArgumentByRef<T>(i, a) is inserted, one for each argument, where i is the index of the argument, v is a value, t a type, and a a managed pointer.

Each exception filter starts with a callback to StartFilter(r) where r is the reference to the exception object that is currently being filtered. Each exception handler starts with a callback to StartExceptionHandler(r).

Each instruction that can throw a NullReferenceException, InvalidCastException, IndexOutOfRangeException, ArrayTypeMismatchException, DivideByZeroException or OverflowException is immediately followed by a callback that indicates that the instruction did not throw the exception. Also, all such instructions are surrounded by an exception handler, that catches the corresponding exception type, performs a callback to a method that indicates that the exception was thrown, and rethrows the exception.

See the file checks.def in the Microsoft.ExtendedReflection.ClrMonitor project for detailed information about which instructions may throw which exceptions.

In general, each instruction causes a callback named after the instruction itself. The callback is issued before the execution of the actual instruction.

In order to capture all relevant information to track the execution path taken by the program, some instructions get a special treatment.

Substitutions


Call instruction in instrumented MSIL code can be redirected. Read more here.

Setup


In order for code to be monitored, certain environment variables must be set before the process starts:

COR_ENABLE_PROFILING=1
COR_PROFILER={C1DAAFC4-10C6-4838-9F89-435E2120F5F1}

CLRMONITOR_FLAGS={flags that decide the extend of the instrumentation}

  • which type and assemblies should be instrumented?
CLRMONITOR_INSTRUMENT_TYPES={comma-separated list of type names; case matters; generic types must end in '`n' annotations; nested types are separated by '+'; <Module> stands for all module-level members}
 
CLRMONITOR_INSTRUMENT_ASSEMBLIES={comma-separated list of display names of assemblies; case does not matter; use '*' for all assemblies}
 
CLRMONITOR_INSTRUMENT_TYPES_EXCLUSIONS={list of types which should not be instrumented, despite the above}
 
CLRMONITOR_INSTRUMENT_ASSEMBLIES_EXCLUSIONS={list of assemblies which should not be instrumented, despite the above}
 
CLRMONITOR_DISABLE_MSCORLIB_SUPPRESSIONS=1, disable mscorlib exclusions. Use with *Great* care.

  • which types and assemblies should be instrumented so that values can be injected at any place in the execution
CLRMONITOR_INJECT_TYPES={comma-separated list of type names; case matters; generic types must end in '`n' annotations; nested types are separated by '+'; <Module> stands for all module-level members}
 
CLRMONITOR_INJECT_ASSEMBLIES={comma-separated list of display names of assemblies; case does not matter; use '*' for all assemblies}
 
CLRMONITOR_INJECT_TYPES_EXCLUSIONS={list of types which should not be instrumented, despite the above}
 
CLRMONITOR_INJECT_ASSEMBLIES_EXCLUSIONS={list of assemblies which should not be instrumented, despite the above}

  • which method calls should be substituted (redirected)?
CLRMONITOR_SUBSTITUTIONS={comma-separated list of file names, pointing to assemblies containing substitutions}

  • which instructions should be monitored by inserted callbacks?
See here for a detailed description of possible CLRMONITOR_FLAGS.

The class Monitoring.Controller in the Microsoft.ExtendedReflection project provides support to check if code in the current process can be monitored, and to setup monitoring for a new process.

Activation


There are two ways to direct the instrumented code's callbacks to a user-written managed class:

  • In a running process, the Monitoring.Controller class provides Start and Stop methods to direct the callbacks to a particular Execution Monitor and to stop the redirection.
  • When the following environment variables are set, a user-provided Execution Monitor is loaded automatically into any monitored process. Note that in addition to setting up the environment variables, the Microsoft.ExtendedReflection assembly must either be in the monitored process' application directory, or in the GAC.

CLRMONITOR_USER_ASSEMBLY={file name of assembly containing [Execution Monitor]}
 
CLRMONITOR_USER_TYPE={type in assembly implementing [Execution Monitor]}

Logging (Only available in Debug-builds)


If compiled in Debug configuration, setting the environment variable

CLRMONITOR_LOGFILE={filename}
CLRMONITOR_VERBOSE=1

causes detailed information about the code instrumentation to be stored in the indicated file.


Debugging (Only available in Debug-builds)


If set, this environment variable will cause the ClrMonitor to break into the debugger when launched.

CLRMONITOR_BREAK=1

Code Substitutions


Some methods are problematic for Pex' symbolic analysis:
  • methods implemented by native code (x86, X64)
  • method calls going through remoting
  • managed code which is not instrumented (e.g. some parts of mscorlib cannot be instrumented)

The Microsoft.ExtendedReflection library has several ways to deal with this problem.