Pex - Automated Exploratory Testing for .NET

// no parameters, using 'closed' unit tests
[TestMethod]
public void AddMoney() {
Account account = new Account();
account.Add(100);
Assert.IsTrue(account.Amount == 100);
}
// 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);
}
[TestClass]
class Test {
[PexMethod] void Foo(int i) {... }
[TestMethod] void Bar() { ... }
}

[PexMethod]
void ReplaceFirstChar(string target, char c) {
string result = StringHelper.ReplaceFirstChar(target, c);
Assert.AreEqual(result[0], c);
}
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);
}
}
[TestMethod, ExpectedException(typeof(ArgumentNullException))]
void ReplaceFirstChar0() {
this.ReplaceFirstChar(null, 0);
}
...
[TestMethod]
void ReplaceFirstChar10() {
this.ReplaceFirstChar("a", 'c');
}
| Feature | Visual Studio Unit Test | xUnit.net | Description |
|---|---|---|---|
| fixture | [TestClass, PexClass] | [PexClass] | tests are logically grouped in a type |
| parameterized test | [PexMethod] | instance method tagged with PexMethod | same |
| fixture setup | [ClassInitialize] | supported | not supported |
| fixture teardown | [ClassCleanup] | supported | not supported |
| test setup | [TestInitialize] | supported | not supported |
| test teardown | [ClassCleanup] | supported | not supported |
[assembly: PexAssemblySettings(TestFramework = "Repro")]


| Add Pex reference | Microsoft.Pex.Framework.dll |
| Bind test project | [assembly: PexAssemblyUnderTest("UnderTest")] |
| 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); } }
| PexAssume | evaluates assumptions (input filtering) |
| PexAssert | evaluates assertions |
| PexChoose | generates new choices (additional inputs) |
| PexObserve | logs live values to the report and/or generated tests |
[PexMethod] void StaticHelpers(Foo target){ PexAssume.IsNotNull(target); int i = PexChoose.FromCall(this).ChooseValue<int>("i"); string result = target.Bar(i); PexObserve.ValueForViewing<string>("result", result); PexAssert.IsNotNull(result); }
| PexAssemblyUnderTestAttribute | binds a test project to a project |
| PexInstrumentAssemblyAttribute | specifies to instrument an assembly |
[assembly: PexAssemblyUnderTest("MyAssembly")] // also instruments "MyAssembly" [assembly: PexInstrumentAssembly("Lib")]
[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 { ... }
[assembly: PexAssemblyUnderTest("MyAssembly")]
[TestClass, PexClass(typeof(Foo))] public partial class FooTestClass { ... }
[assembly: PexAllowedExceptionFromTypeUnderTest(typeof(ArgumentException))]
[assembly: PexAllowedContractRequiresFailureAtTypeUnderTestSurface]
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();
}
}

[PexClass]
public partial class MyTests {
[PexMethod]
public void MyTest(int i)
{ ... }
}
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!");
}
}
| Test Number | value |
| 1 | "" |
| 2 | "\0\0\0\0\0\0" |
| 3 | "Hellol" |
| 4 | "HellolWorld!" |
| 5 | "Hello World!" |
[TestMethod()]
[PexRaisedException(typeof(Exception))]
public void HelloWorld05()
{
this.HelloWorld("Hello World!");
}
[PexMethod]
public void Test1(object o) {
// precondition: o should not be null
PexAssume.IsNotNull(o);
...
}
[PexMethod]
public void Test2([PexAssumeNotNull] object o)
// precondition: o should not be null
{
...
}
[PexClass]
public partial class ListTest {
[PexMethod]
[PexGenericArguments(typeof(int))]
[PexGenericArguments(typeof(object))]
public void AddItem<T>(List<T> list, T value)
{ ... }
}
public void TestSomething(int i, int j) {
PexAssume.AreNotEqual(j, 0);
int k = i/j;
...
}
if (j==0)
return;
[PexMethod]
public void Test(int i)
{
if (i>0)
Console.WriteLine("positive");
}


public int Foo() {
var chooser = PexChoose.FromCall(this);
return chooser.ChooseResult<int>();
}
public void Test() {
ArrayList list = new ArrayList();
while(PexChoose.DefaultSession.ChooseValue<bool>("next"))
list.Add(null);
...
}
interface INamed {
string GetName();
}
class MNamed : INamed {
public string GetName() {
var call = PexChoose.FromCall(this);
return call.Result<string>();
}
}
var call = PexChoose.FromCall(this);
return call.Result<string>();
[PexMethod]
public void GetName() {
var name = new MName();
if (name.GetName() == "Marc")
Console.WriteLine("hello marc");
}
// test 2
MockTest.MNamed mn0 = new MockTest.MNamed();
var chooser = PexChoose.NewTest();
chooser.OnCall(0, "MNamed.GetName()")
.Returns("Marc");
this.GetName();
// on the call '0' to the method GetName of MockType.MNamed,
choose.OnCall(0, "MNamed.GetName()")
// return "Marc"
.Returns("Marc");
class MNamed : INamed {
private string name;
public string GetName() {
if(this.name == null)
this.name = PexChoose.FromCall(this).ValueNotNull<string>("name");
return this.name;
}
}
using Microsoft.Pex.Framework; // overriding the test framework selection [assembly: PexAssemblySettings(TestFramework = "Naked")]
COR_ENABLE_PROFILING=1
COR_PROFILER={C1DAAFC4-10C6-4838-9F89-435E2120F5F1}
CLRMONITOR_FLAGS={flags that decide the extend of the instrumentation}
CLRMONITOR_PROTECT_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_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.
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}
CLRMONITOR_SUBSTITUTIONS={comma-separated list of file names, pointing to assemblies containing substitutions}
CLRMONITOR_USER_ASSEMBLY={file name of assembly containing [Execution Monitor]}
CLRMONITOR_USER_TYPE={type in assembly implementing [Execution Monitor]}
CLRMONITOR_LOGFILE={filename}
CLRMONITOR_VERBOSE=1
CLRMONITOR_BREAK=1
CLRMONITOR_CLSID={...}
| Pex Shortcut | Description |
|---|---|
| Ctrl + E, E | Run Explorations in Current context |
| Ctrl + E, P | Run Explorations in Current project |
| Ctrl + E, Ctrl + E | Run Explorations in the Last Pex Run |


[TestClass]
[PexClass]
public partial class MyPexClass
{
[PexMethod]
public void Test(int i)
{
// add parameterized test here
}
}
// monitor types in MyProduct.dll [assembly: PexInstrumentAssembly(typeof(SomeTypeInMyProduct))]
public static class StringHelper
{
public static string ReplaceFirst(string s, char c)
{
return c + s.Substring(1);
}
}
// monitor types in MyLibrary.dll [assembly: PexInstrumentAssembly(typeof(StringHelper))]

[TestClass, PexClass]
public partial class StringHelperFixture
{
[PexMethod]
public void MyPutTest(int i)
{
// add parameterized test here
}
}
[PexMethod]
public void ReplaceFirst(string value, char c)
{
// invoke method under test with parameter values
string result = StringHelper.ReplaceFirst(value, c);
// verify assertions
if (!String.IsNullOrEmpty(value))
{
// first character was replaced
Assert.AreEqual(c, value[0]);
// the rest of the string is not modified
Assert.AreEqual(value.Substring(1), result.Substring(1));
}
}
"%programfiles%\microsoft pex\bin\pex.exe" MyLibrary.Tests.dll
Pex: Program Exploration Framework for .Net
Copyright (c) Microsoft Corporation. All rights reserved.
Microsoft Confidential - for Internal Use Only
instrumenting... launched Pex x86 Edition
(...)
15:08:55.04> MyLibrary.Tests
15:08:55.05> MyLibrary.Tests.StringHelperFixture
15:08:55.08> ReplaceFirst(String, Char)
[test] ReplaceFirstStringChar_61102_150857_0, System.NullReferenceException: Object reference not set to an instance of an object.
[test] ReplaceFirstStringChar_61102_150858_1, System.ArgumentOutOfRangeException: startIndexcannot be larger than length of string.
Parameter name: startIndex
(...)
15:08:59.21> Finished execution: 1 explorations, 0 failures, 2 generated tests (1 failures, 0 duplicates), 00:00:07.3567
(...)
EXPLORATION SUCCESS

public static string ReplaceFirst(string s, char c)
{
if (String.IsNullOrEmpty(s))
throw new ArgumentNullException("s");
if (s.Length == 1)
return c.ToString();
else
return c + s.Substring(1);
}
"%programfiles%\microsoft pex\bin\pex.exe" MyLibrary.Tests.dll
Pex: Program Exploration Framework for .Net
(...)
15:12:44.78> MyLibrary.Tests
15:12:44.80> MyLibrary.Tests.StringHelperFixture
15:12:44.83> ReplaceFirst(String, Char)
[test] ReplaceFirstStringChar_61102_151247_0, System.ArgumentNullException: Value cannot be null.
Parameter name: s
[test] ReplaceFirstStringChar_61102_151248_1
[test] ReplaceFirstStringChar_61102_151248_2
[instrumentation] System.Char.ToString not instrumented
[instrumentation] System.String.Concat not instrumented
(...)
15:12:49.61> Finished execution: 1 explorations, 0 failures, 3 generated tests (0 failures, 0 duplicates), 00:00:08.0440
940
(...)
EXPLORATION SUCCESS
public partial class StringHelperFixture
{
[TestMethod]
[ExpectedException(typeof(System.ArgumentNullException))]
public void ReplaceFirstStringChar_61102_151247_0()
{
this.ReplaceFirst(((string)(null)), '\0');
}
[TestMethod]
public void ReplaceFirstStringChar_61102_151248_1()
{
string s0 = "x";
this.ReplaceFirst(((string)(s0)), 'x');
}
[TestMethod]
public void ReplaceFirstStringChar_61102_151248_2()
{
string s0 = "xx";
this.ReplaceFirst(((string)(s0)), 'x');
}
}

[Test]
void MyTest() {
// data
ArrayList a = new ArrayList();
// method sequence
a.Add(5);
// assertions
Assert.IsTrue(a.Count==1);
Assert.AreEqual(a[0], 5);
}
pex.exe /erm:unittest myunittests.dll
public void TestSomething(int i, int j) {
PexAssume.AreNotEqual(j, 0);
int k = i/j;
...
}
if (j==0)
return;
| Note: Use this attribute only if Pex may set all fields of a class in any (type-correct) way. Consider using an attribute deriving from PexExplorableAttributeBase if in doubt. |
public class Point {
public int X,Y;
}
public class Point {
public readonly int X;
public readonly int Y;
public Point(int x, int y) {
this.X = x;
this.Y = y;
}
}
// binding
[PexCreatableByConstructor(typeof(Point), typeof(int), typeof(int))]
public class Point {
...
public static Point Create(int x, int y) {
Point point = new Point();
point.X = x;
point.Y = y;
return point;
}
}
// binding
[PexCreatableByMethod(typeof(Point), "Create", typeof(int), typeof(int))]
public class Point {
private Point() {...}
public static Point Instance { get {...} }
}
// binding
[PexCreatableAsSingleton(typeof(Point), "Instance")]
public class Account {
private float money;
public Account(Bank bank, string name) {
// control-flow in the constructor
if (bank == null) throw new ArgumentNullException();
if (name == null) throw new ArgumentNullException();
// calls to other method
this.money = bank.GetMoney(name);
}
public float Money {
get { return this.money; }
}
}
// test that needs an instance of Account
[PexMethod]
public void NeedsAccount(Account a) {
Assert.IsTrue(a.Money >= 0);
}
// binding [assembly: PexExplorableFromConstructor(typeof(Account), typeof(Bank), typeof(string))]
// load any factories from this assembly
[assembly: PexExplorableFromFactories]
...
// this type contains factories
[PexClassFactory]
public static class AccountFactory {
// this is a factory that creates 'Account' instances
[PexMethodFactory(typeof(Account))]
public static Account Create(Bank bank, string name) {
return new Account(bank, name);
}
}
public int Foo(object a, out string b, ref string c);
var call = PexChoose.FromCall(this);
b = call.ChooseValueAtReturn<string>(2); // you can also get a value for 'ref' parameters
return call.ChooseResult<int>();
public int Foo(object a, out string b, ref string c) {
var call = PexChoose.FromCall(this);
b = call.ChooseValueAtReturn<string>(2);
return call.ChooseResult<int>();
}
// interface to be mocked
public interface IFoo {
string Getter { get; }
// assume is not null
object GetterSetter { get; set; }
}
public class MFoo : IFoo {
private PexOracleValue<string> getter;
private PexOracleValueNotNull<object> getterSetter;
public MFoo() {
this.setter =
new PexOracleValue<string>(this, "Getter");
this.getterSetter =
new PexOracleValueNotNull<object>(this, "GetterSetter");
}
public string Getter {
get { return this.getter.Value; }
}
public object GetterSetter {
get { return this.getterSetter.Value; }
get { this.getterSetter.Value = value; }
}
}
interface IFoo {
event EventHandler Boo;
}
class MFoo : IFoo {
public event EventHandler Boo;
}
[ComImport]
interface IWorker
{
// if returns S_OK, Foo is set
int GetValue(out Foo result);
}
class MWorker : IWorker
{
public int GetValue(out Foo result)
{
var call = PexChoose.FromCall(this);
int hr = call.ChooseHResult();
if (hr == PexChoose.HResults.S_OK)
result = call.ChooseValueAtReturn<Foo>(1);
else
result = default(Foo);
return hr;
}
}
[PexMethod, PexAllowedException(typeof(ArgumentNullException))]
void SomeTest() {...}
| Name | Default value | Deduced from project | Command Line | Assembly setting |
|---|---|---|---|---|
| test framework | test assembly references inspection | no | yes | yes |
| test language | C# | yes | no | yes |
| assembly root namespace | test assembly name | yes | no | no |
| output path | <report>\tests | <test project path> | no | no |
using Microsoft.Pex.Framework;
[assembly: PexAssemblySettings(MaxBranches = 1000)] // we override the default value of maxbranches
namespace MyTests
{
[PexClass(MaxBranches = 500)] // we override the 1000 value and set maxbranches to 500
public partial class MyTests
{
[PexMethod(MaxBranches = 100)] // we override again, maxbranches = 100
public void MyTest(...) { ... }
}
}
// command line
pex.exe ... /maxbranches:50 // command line parameter overrides again, maxbramches = 50, final!
[assembly: InternalsVisibleTo("Microsoft.Pex, PublicKey=76a274db078248c8")]
// we'd like all explorations in the assembly to reach at least 70% coverage [assembly: PexExpectedCoverage(70)]
[PexClass]
[PexExpectedTests(NewCount = 0)] // notify my if any new test gets created
public class MyTest
{ ... }
[TestClass, PexClass]
public partial class CalendarTest {
[PexMethod]
public string GetMonth(int i) {
string month = Calendar.GetMonthName(i);
// storing output, giving it a name
return month;
}
}
[TestMethod]
public void GetMonth01() {
// invoke parameterized unit test, which associates names to computed values
string result = GetMonth(1);
// verifying that we received the expected named value
// we expect "January", because that was the value Pex saw when generating this test
Assert.AreEqual("January", result);
}
...
[assembly: PexAssemblySettings(TestCopyright = @" ---------------------- (c) Microsoft Corporation. All rights reserved. ------------------------")]
// ---------------------- // (c) Microsoft Corporation. All rights reserved. // ------------------------ ...
pex .... /driver=c:\debuggers\windbg.exe
public sealed class SvnSourceControlAttribute :
PexProcessSourceControlAttributeBase {
public SvnControlAttribute (string toolPath)
: base("svn", "svn.exe")
{ }
protected override string GetAddArguments(string fileName) {
return SafeString.Format("add \"{0}\"", fileName);
}
protected override string GetCheckOutArguments(string fileName) {
return SafeString.Format("edit \"{0}\"", fileName);
}
}
// assemblyinfo.cs
[assembly: SvnSourceControl]
pex ... /sc:svn
pex /sympath:srv*c:\symbols*http://msdl.microsoft.com/download/symbols
[TestClass] // this class contains unit tests
public partial class MyTestFixture {
// this is a unit test
[TestMethod]
public void UnitTest() {...}
// this is a parameterized unit test
[PexMethod]
public void ParameterizedTest(int i) {...}
// this is a generated unit test
// from ParameterizedTest
[TestMethod, ...]
public void ParameterizedTest_1() {
this.ParameterizedTest(0);
}
}
[TestClass]
public class MyFixture
{
[TestInitialize] public void SetupStuffForMyTests() {...}
[TestCleanup] public void SetupStuffForMyTests() {...}
}
namespace MyTests
{
using Microsoft.Pex.Framework;
using MbUnit.Framework;
[assembly: AssemblyCleanup(typeof(MyAssemblySetup))]
public static class MyAssemblySetup {
[SetUp]
public static void SetUp() {
Console.WriteLine("assembly setup");
}
}
[TestFixture]
public partial class MyTests {
[TestFixtureSetUp]
public void FixtureSetUp() {
Console.WriteLine("some fixture wide setup here");
}
[TestFixtureTearDown]
public void FixtureTearDown() {
Console.WriteLine("some fixture wide teardown here");
}
[SetUp]
public void SetUp() {
Console.WriteLine("monitored setup");
}
[PexMethod]
public void MyTest(int i ) {...}
[TearDown]
public void TearDown() {
Console.WriteLine("Clean up");
}
}
}
MyAssemblySetup.SetUp MyTests.FixtureSetUp MyTests.SetUp MyTests.MyTest MyTests.TearDown ... MyTests.SetUp MyTests.MyTest MyTests.TearDown MyTests.FixtureTearDown
[PexMethod]
[PexIgnore("ignore reason")]
public void MyTest(int i) {...}
[PexMethod]
[PexIgnore("ignore reason", WorkItemId = 12345)]
public void MyTest(int i) {...}

test123.g.cs
// fixture type
[TestClass, PexClass]
public partial class MyTest {
[PexMethod]
[CssProjectStructure("xxx"), CssIteration("yyy")]
[WorkItem(1), WorkItem(2)]
public void Foo(int i) {...}
}
// generated tests
public partial class MyTest {
[TestMethod]
[CssProjectStructure("xxx")]
[CssIteration("yyy")]
[WorkItem(1)]
[WorkItem(2)]
public void Foo_1234() { ... }
}
[PexMethod, Category("very important")]
public void Important(int i) {...}
[Test, ...]
[Category("very important")]
public void Important_1234_213_1() {...}
pex.exe /rc
pex.exe /rc /rmc 10




pex.exe mypexassembly.dll
pex.exe ... /nf:MyTests.Current
pex.exe ... /tf:MyTests
pex.exe ... /mf:SquareTest
pex.exe ... /cf:data;web
pex.exe ... /sf:checkin
pex.exe ... /if
pex.exe ... /nf:<namespace> /tf:<type name> /mf:<method name>
pexwizard.exe <your assembly name>
pex.exe <generated parameterized test stubs.dll> [more options]
// MyCustomTestFramework.dll contains a custom test framework pexwizard.exe ... /sa:MyCustomTestFramework.dll
using (_ProtectingThreadContext.Acquire())
{
// your code
}
// extension project
public sealed class MyExtensionsPackageAttribute
: PexPackageAssemblyAttribute
{}
[assembly: PexInstrumentAssembly("Foo")]
[assembly: PexFocusOnAssembly("Foo")]
...
[assembly: PexPackageType(typeof(MyLibrary))]
...
[PexFocusOnAssembly("Foo")]
static class MyLibrary {
}
// test project [assembly: MyExtensionsPackage]
[assembly: PexGraphPackage]
| Exit Code Value | Name |
|---|---|
| 0 | success |
| 0xC000013A | Control C |
| 0x80131506 | fatal execution engine error 1 |
| 0x800703E9 | fatal execution engine error 2 |
| 0xE0434F4D | CLR error |
| Exit Code Value | Name |
|---|---|
| -666 | assertion or assumption |
| -667 | CLR Monitor failure |
| Exit Code Value | Name |
|---|---|
| -1 | unknown |
| -999 | user aborted |
| -1000 | default failure |
| -1001 | unknown pointer size |
| -1003 | options parsing error |
| -1004 | error in sandbox |
| -1005 | no channel set |
| -1006 | assembly load error |
| -1007 | platform mistmatch |
| -1008 | unexpected tool error |
| -1009 | unexpected launch error |
| -1010 | reflection error |
| -1011 | unrecoverable error while reflecting tests |
| -1012 | could not find the test assembly |
| -1013 | could not find any test to run |
| -1014 | instrumention driver configuration error |
| -1015 | external profiler registered |
| -1016 | monitoring of X86 code not enabled |
| -1017 | monitoring of X64 code not not enabled |
| -1018 | remoting connection could not be established |
| -2000 | Visual Studio Build failed |
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<!-- indicates if Pex was installed -->
<Fragment>
<Property Id="PEX" Secure="yes">
<RegistrySearch
Id="PexConsoleSearch"
Root="HKLM"
Key="Software\Microsoft\Pex\CurrentVersion"
Name="InstallPath"
Type="raw"
Win64="no" />
</Property>
</Fragment>
</Wix>
... tracer loaded [1] <enter> ConsoleApplication.Program.Main [1] <enter> ConsoleApplication.Program.Foo [1] <leave> [1] <leave>
gacutil /i (proper directory)\Microsoft.ExtendedReflection.dll regsvr32 /i (proper directory)\Microsoft.ExtendedReflection.ClrMonitor.X86.dll
RegisterTracer.cmd
Watch it!
[TestClass, PexClass]
public partial class ChunkerTest {
[PexMethod]
public void Chunk(string value, int length) {
Chunker chunker = new Chunker(value, length);
string result = null;
for (string chunk = chunker.Next();
chunk != null;
chunk = chunker.Next())
result += chunk;
Assert.AreEqual(value, result);
}
}
public class Chunker {
public Chunker(string value, int length) { }
public string Next() {
return null;
}
}
[TestMethod(), ...]
public void ChunkStringInt32_70312_151917_0_01() {
this.Chunk(((string)(null)), -1);
}
[TestMethod(), ...]
[PexUnexpectedException(typeof(AssertFailedException))]
public void ChunkStringInt32_70312_151917_0_02() {
string s0 = "";
this.Chunk(((string)(s0)), -1);
}
public class Chunker {
string value;
int length, index;
public Chunker(string value, int length) {
this.value = value;
this.length = length;
}
public string Next() {
string chunk = this.value.Substring(this.index, this.length);
this.index += this.length;
return chunk;
}
}
public Chunker(string value, int length) {
// <pex>
if (value == null)
throw new ArgumentNullException("value");
if (length < 0 | value.Length < length)
throw new ArgumentException("length < 0 | value.Length < length");
// </pex>
this.value = value;
this.length = length;
}
if (length <= 0 | value.Length > length)
throw new ArgumentOutOfRangeException();
string chunk;
if (this.index > this.value.Length)
chunk = null;
else
chunk = this.value.Substring(this.index, this.length);
string chunk;
if (this.index > this.value.Length)
chunk = null;
else if (this.index + this.length > this.value.Length)
chunk = this.value.Substring(this.index);
else
chunk = this.value.Substring(this.index, this.length);
| Tip: The project type "Web Application" which simplifies testing such web services. |
// assume foo is not null
[PexMethod]
public void SomeTest([PexAssumeNotNull]IFoo foo, ...) {}
public class Foo {
// this field should not be null
[PexAssumeNotNull]
public object Bar;
}
// never consider null for Foo types
[PexAssumeNotNull]
public class Foo {}
public void Test(int i) {
int j = Math.Abs(i);
PexAssert.IsTrue(j >= 0);
}
PexObserve.Value<string>("result", result);
// product code
public static class MathEx {
public static int Square(int value) { return value * value; }
}
// fixture
[TestClass]
public partial class MathExTests {
[PexMethod]
public int SquareTest(int a) {
int result = MathEx.Square(a);
// storing result
return result;
}
}
[assembly: PexAssemblyUnderTest("MyAssembly")]
using Microsoft.Pex.Framework;
// the assembly containing ATypeFromTheAssemblyToInstrument should be instrumented
[assembly: PexInstrumentAssembly(typeof(ATypeFromTheAssemblyToInstrument))]
// the assembly name can be used as well
[assembly: PexInstrumentAssembly("MyAssemblyName")]
[TestClass]
publi class FooTest
{
[TestMethod]
public void SomeTestOnFoo() {...}
}
[PexClass(MaxRuns = 10)]
public partial class FooTest {...}
namespace MyTests
{
using Microsoft.Pex.Framework;
using MbUnit.Framework;
[assembly: AssemblyCleanup(typeof(MyAssemblySetup))]
public static class MyAssemblySetup
{
[SetUp]
public static void SetUp()
{
Console.WriteLine("assembly setup");
}
}
[TestFixture, PexClass]
public partial class MyTests
{
[TestFixtureSetUp]
public void FixtureSetUp()
{
Console.WriteLine("some fixture wide setup here");
}
[SetUp]
public void SetUp()
{
Console.WriteLine("monitored setup");
}
[PexMethod]
public void MyTest(int i ) {...}
}
}
// exclude MyTest type [assembly: PexCoverageFilterType(PexCoverageDomain.Excluded, typeof(MyTest))]
void Test([PexAssumeUnderTest]Foo target, int value) {
// precondition: target is under test, we don't care about a null value
target.Bar(value);
}
[PexMethod]
[PexUseType(typeof(A))]
[PexUseType(typeof(B))]
public void MyTest(object testParameter)
{
... // Pex will consider types A and B to instantiate 'testParameter'
}
public partial class MyTest {
[PexMethod]
[PexIgnore("Blocked by bug", WorkItem = 123) ]
public void SomeTest(int i ) {...}
}
[PexClass]
[PexIgnore("Not implemented yet") ]
public partial class MyTest {
[PexMethod]
public void SomeTest(int i ) {...}
}
[assembly: PexSuppressStackFrameFromNamespace("Microsoft.VisualStudio.QualityTools.UnitTestFramework")]
[assembly: PexSuppressUninstrumentedMethodFromAssembly("MyAssembly")]
[assembly: PexSuppressUninstrumentedMethodFromNamespace("System.Collections")]
[TestClass, PexClass]
public partial class ArrayListTest {
[PexMethod]
[PexCrossProductExplorableStrategy(MaxLength=3)]
[PexExplorableMutator(typeof(ArrayList), "Add")]
[PexExplorableMutator(typeof(ArrayList), "Remove")]
public Insert([PexAssumeNotNull]ArrayList list, int index, object elem) {
list.Insert(index, elem);
PexAssert.True(list.Contains(elem));
}
}
public class Node {
public Node() {}
public int Left;
public Node Right { get; set; }
}
[assembly: PexExplorableFromConstructorAndSetters(typeof(Node))]
public abstract class Tree {
public sealed class Leaf : Tree {
private int value;
public Leaf(int value) {
this.value = value;
}
public int Value {
get { return this.value; }
}
}
public sealed class Node : Tree {
private Tree left, right;
public Node(Tree left, Tree right){
PexAssume.NotNull(left);
PexAssume.NotNull(right);
this.left = left;
this.right = right;
}
public Tree Left {
get { return this.left; }
}
public Tree Right {
get { return this.right; }
}
}
}
[assembly: PexExplorableFromConstructor(
typeof(Tree.Leaf), // class can be explored from its constructor which takes
typeof(int))] // one parameter of type int
[assembly: PexExplorableFromConstructor(
typeof(Tree.Node), // class can be explored from its constructor which takes
typeof(Tree), typeof(Tree))] // two parameters of type Tree
[PexMethod]
[PexUseType(typeof(Tree.Leaf))]
[PexUseType(typeof(Tree.Node))]
public void TestTree(Tree t) {
Tree.Node n = t as Tree.Node;
if (n != null) {
Tree.Node nl = n.Left as Tree.Node;
if (nl != null) {
Tree.Node nlr = nl.Right as Tree.Node;
if (nlr != null) {
Tree.Leaf nlrr = nlr.Right as Tree.Leaf;
if (nlrr != null && nlrr.Value == 42)
throw new Exception("found it");
}
}
}
}
Tree.Leaf l0 = new Tree.Leaf(42); Tree.Node n0 = new Tree.Node(l0, l0); Tree.Node n1 = new Tree.Node(l0, n0); Tree.Node n2 = new Tree.Node(n1, n1); this.TestTree(n2); // throws Exception
[assembly: PexExplorableFromFactories("MyAssembly.Tests")]
class Account {
public int Money {get; set;} // can't be set publicaly
public readonly int ID; // can only be set through the ctor
private Account(int ID) { this.ID = id; } // private .ctor
// this is the factory we'll need to call
// in general, this can be a non-trivial guess for Pex
static Account Create(int id) {
return new Account(id);
}
}
public static class AccountFactory {
// factory for the Account type that
// sets the ID and Money field
[PexFactoryMethod(typeof(Account))]
public static Account CreateAccount(int id, int money) {
return Account.Create(id) { Money = money; }
}
}
public abstract class Tree {
public sealed class Leaf : Tree {
private int value;
internal Leaf(int value) {
this.value = value;
}
public int Value {
get { return this.value; }
}
}
public sealed class Node : Tree
{
private Tree left, right;
internal Node(Tree left, Tree right) {
PexAssume.IsNotNull(left);
PexAssume.IsNotNull(right);
this.left = left;
this.right = right;
}
public Tree Left {
get { return this.left; }
}
public Tree Right {
get { return this.right; }
}
}
public static Tree MakeLeaf() { return new Leaf(); }
public static Tree MakeNode(Tree left, Tree right) {
return new Node(left, right);
}
}
[assembly: PexExplorableFromConstructor(
typeof(Tree.Leaf), // class that we create instances of
typeof(Tree), // declaring type of factory method
"MakeLeaf", // name of factory method
typeof(int))] // parameters of factory method
[assembly: PexExplorableFromConstructor(
typeof(Tree.Node), // class that we create instances of
typeof(Tree), // declaring type of factory method
"MakeNode", // name of factory method
typeof(Tree), typeof(Tree))] // parameters of factory method
[PexMethod]
[PexUseType(typeof(Tree.Leaf)), PexUseType(typeof(Tree.Node)), PexUseType(typeof(Tree))]
public void TestTree(Tree t) {
Tree.Node n = t as Tree.Node;
if (n != null) {
Tree.Node nl = n.Left as Tree.Node;
if (nl != null) {
Tree.Node nlr = nl.Right as Tree.Node;
if (nlr != null) {
Tree.Leaf nlrr = nlr.Right as Tree.Leaf;
if (nlrr != null && nlrr.Value == 42)
throw new Exception("found it");
}
}
}
}
Tree.Leaf _r0 = Tree.MakeLeaf(42); Tree.Node _r1 = Tree.MakeNode(_r0, _r0); Tree.Node _r2 = Tree.MakeNode(_r0, _r1); Tree.Node _r3 = Tree.MakeNode(_r2, _r2); this.TestTree(_r3); // throws Exception
[TestClass, PexClass]
public partial class ArrayListTest {
[PexMethod]
[PexExplorableMutator(typeof(ArrayList), "Add")]
[PexExplorableMutator(typeof(ArrayList), "Remove")]
public Insert([PexAssumeNotNull]ArrayList list, int index, object elem) {
list.Insert(index, elem);
PexAssert.IsTrue(list.Contains(elem));
}
}
[PexMethod]
[PexInjectExceptionsOnUnverifiableUnsafeMemoryAccess]
unsafe public void TestWithPointers(int i)
{
fixed (char* p = "Hello")
{
if (*(p + i) == 'l')
Console.WriteLine("l");
}
}
class Stack {
int[] _elements;
int _count;
public Stack(int capacity) {
if (capacity<0) throw new ArgumentOutOfRangeException();
_elements = new int[capacity];
_count = 0;
}
...
}
[PexMethod]
[PexAllowedException(typeof(ArgumentOutOfRangeException))]
class CtorTest(int capacity) {
Stack s = new Stack(capacity); // may throw ArgumentOutOfRangeException
}
using Microsoft.Pex.Framework;
...
[TestClass]
[PexExpectedCoverage(100)] // we expect to cover 100%, on each test
public partial class MyTest
{
...
}
class Stack {
int[] _elements;
int _count;
public Stack(int capacity) {
_elements = new int[capacity];
_count = 0;
}
public void Pop() {
if (_count==0) throw new InvalidOperationException();
...
}
}
[PexMethod]
[PexExpectedException(typeof(InvalidOperationException))]
void PopFailureTest(int capacity) {
Stack s = new Stack(capacity);
s.Pop(); // should throw InvalidOperationException
}
using Microsoft.Pex.Framework;
...
[TestClass]
[PexClass]
[PexExpectedTests(TotalCount = 5)] // we expect to create 5 tests
public partial class MyTest
{
...
}
// in the product
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class MyInstrumentedAttribute : Attribute {}
// marking types
[MyInstrumented]
public static class MyAssert { ... }
// loading types in pex using Microsoft.Pex.Framework; [assembly: PexInstrumentMarkedBy(typeof(MyAssert), typeof(MyAssert))]
// we want to instrument all types in the namespace MyNamespace.Sub contained in the assembly that contains the type SomeTypeOfAnAssembly. [assembly: PexInstrumentNamespace(typeof(SomeTypeOfAnAssembly), "MyNamespace.Sub")]
// we want to instrument a custom assertion type [assembly: PexInstrumentType(typeof(MyCustomAssert))]
// MySubstitutionType is a type of the assembly that contains // the substitutions [assembly: PexSubstitutionAssembly(typeof(MySubstitutionType))]
[assembly: PexFocusOnAssembly(typeof(SomeTypeDefinedInTheProductAssembly))]
[assembly: PexFocusOnNamespace(typeof(SomeTypeDefinedInTheProductAssembly), "MyProduct.SomeSubnamespace")]
[PexMethod]
[PexFocusOnType(typeof(A))]
[PexFocusOnType(typeof(B))]
[PexFocusOnType(typeof(C))]
public void EqualsTest(object a, object b)
{
PexAssume.IsTrue(a!=null && a.Equals(b));
PexAssert.AreEqual(a.GetHashCode(), b.GetHashCode());
}
public class MySingletonType {
private MySingletonType() {}
public static readonly MySingletonType TheInstance = new MySingletonType();
public static bool IsMySingletonType(object o) {
if (o is MySingletonType)
return true;
else
return false;
}
...
}
[assembly: PexCreatableAsSingleton(typeof(MySingletonType), "TheInstance") ]
[PexClass]
public class MyPexTest {
[PexMethod]
public void Test(object o) {
PexAssert.IsTrue(
IsMySingletonType(o) == (o is MySingletonType)
);
}
}
Test(MySingletonType.TheInstance);
Test(null);
public class BigNumber {
// there is no direct way to set these private fields
private int low, high;
public BigNumber(ulong x) {
this.low = (int)x;
this.high = (int)(x>>32);
}
public ulong Value {
get { return ((ulong)(uint)this.low) | (((ulong)(uint)this.high) << 32); }
}
}
public class BigNumberFactory : IPexClassFactory<BigNumber> {
int low, high;
[PexFieldBinding("low")]
public int Low { set { this.low = value; } }
[PexFieldBinding("high")]
public int High { set { this.high = value; } }
public BigNumber Create() {
// here we heave to do the 'reverse' of how the Point encodes its data
return new BigNumber(((ulong)(uint)this.low) | (((ulong)(uint)this.high) << 32));
}
}
[assembly: PexCreatableByClassFactory(typeof(BigNumber), typeof(BigNumberFactory))]
[PexClass]
public class ClassFactoryTests {
[PexMethod]
[PexExpectedTests(TotalCount = 3)]
public void BigNumberTest(BigNumber n) {
if (n!=null && n.Value == 0x0500000007u)
Console.WriteLine("gotcha");
}
}
this.BigNumberTest(null);
BigNumberFactory bnf0 = new BigNumberFactory(); bnf0.Low = -1; bnf0.High = -1; this.BigNumberTest(bnf0.Create());
BigNumberFactory bnf0 = new BigNumberFactory(); bnf0.Low = 7; bnf0.High = 5; this.BigNumberTest(bnf0.Create()); // prints gotcha
| Note: The properties and the Create method of the factory class must not throw exceptions. Not even ArgumentException. They should make 'best effort' to create an instance. Consider using an attribute deriving from PexExplorableAttributeBase. |
public class Point
{
private int _x, _y, _color;
public Point(int x, int y) {
_x = x; _y = y;
}
public int Color {
get { return _color; }
set { color = value; }
}
public int X {
get { return _x; }
}
public void MoveX(int deltaX) {
_x += deltaX;
}
}
[assembly: PexCreatableByConstructorAndSetters(
typeof(Point), // type we want to create instances for
// mapping of fields to properties
"^_(.*)$", // regex pattern applied to all field names, selecting the part of the name after the initial underscore character
"$1", // expression that yields name of property corresponding to field name; "$1" gets instantiated with the part of the field name that falls into the parenthesis above
true, // we want case-insensitive property name matching
// mapping of fields to constructor arguments
"_x", "_y") // two fields must be passed to the constructor and don't have backing property setters
]
[PexClass]
public class PointTestClass
{
[PexMethod]
public void Test(Point p, int deltaX)
{
int oldX = p.X;
p.MoveX(deltaX);
PexAssert.IsTrue(oldX + deltaX == p.X);
}
}
Point p = new Point(0, 0); p.Color = 0; Test(p, 0);
| Note: The parameter types of the constructor must match the field types exactly. Also, neither the constructor nor the setters should throw an exception under any circumstances. Consider using an attribute deriving from PexExplorableAttributeBase instead. |
public class Point {
private int _x, _y, _color;
private Point() {}
public static Point Make(int x, int y) {
Point p = new Point();
p.x = x;
p.y = y;
return p;
}
public int Color {
get { return _color; }
set { color = value; }
}
public int X {
get { return _x; }
}
public void MoveX(int deltaX) {
_x += deltaX;
}
}
[assembly: PexCreatableByMethodAndSetters(
typeof(Point), // type we want to create instances for
// mapping of fields to properties
"_{0}", // string format like pattern applied to all field names,
// selecting the part of the name after the initial underscore character
true, // we want case-insensitive property name matching
// indicating creation method and mapping fields to arguments
typeof(Point), "Make", // declaring type and name of static creation method
"_x", "_y") // two fields must be passed to the creation method and don't have backing property setters
]
[PexClass]
public class PointTestClass {
[PexMethod]
public void Test(Point p, int deltaX) {
int oldX = p.X;
p.MoveX(deltaX);
PexAssert.IsTrue(oldX + deltaX == p.X);
}
}
Point p = Point.Make(0, 0); p.Color = 0; Test(p, 0);
| Note: The parameter types of the creation method must match the field types exactly. Also, neither the creation method nor the setters should throw an exception. Consider using an attribute deriving from PexExplorableAttributeBase if in doubt. |
// web data type (code generated)
[GeneratedCodeAttribute("System.Xml", "2.0.50727.42")]
[SerializableAttribute]
[XmlTypeAttribute(Namespace="http://foo")]
public partial class MyRequest {
private string appIDField;
public string AppID {
get { return this.appIDField; }
set { this.appIDField = value; }
}
}
// tell pex to load all data types from that namespace
[assembly: PexCreatablesAsXmlFromAssembly("SearchAssembly", XmlNamespace = "http://foo")]
[PexClass, ...]
public class MyTests {
[PexMethod]
public void SomeTest(int i) {...}
...
[TestMethod, ...]
[PexGeneratedBy(typeof(MyTests)")]
public void SomeTest_Int_12345()
{...}
}
[TestMethod, ...]
[PexInjectedException(typeof(ThreadAbortException))]
public void SomeTest_1234_1() {...}
// the bug was found by injecting some exception 'artificially'
[TestMethod]
[PexNotReproducible]
...
public void SomeGeneratedTest(){...}
// this test throws a NullReferenceException
[TestMethod, ...]
[PexRaisedException(typeof(NullReferenceException))]
public void MyTest_123456_123_0_2
{...}
// exclude assembly containing the tests, i.e. containing the MyTest class [assembly: PexCoverageFilterAssembly(PexCoverageDomain.Excluded, typeof(MyTest))];
// exclude all types marked with GeneratedCodeAttribute [assembly: PexCoverageFilterMarkedBy(PexCoverageDomain.Excluded, typeof(GeneratedCodeAttribute))]
// exclude all types in namespace ending with 'Tests' [assembly: PexCoverageFilterNamespace(PexCoverageDomain.Excluded, "Tests")]
// we assume Foo's name is not null
public class Foo {
[PexAssumeNotNull]
public string Name;
}
[PexMethod]
public void SomeTest(Foo foo) { ... }
// we assume that foo is not null
[PexMethod]
public void SomeTest([PexAssumeNotNull] IFoo foo) { ... }
public sealed class MyUberTestFrameworkAttribute :
PexTestFrameworkAttributeBase {
protected override ITestFramework CreateTestFramework(
IPexComponent host) {
return new TestFramework(host);
}
class TestFramework : AttributeBasedTestFrameworkBase {...}
}
// this attribute should be in the test assembly or test settings assembly [assembly: MyUberTestFramework] // now you can tell Pex to emit tests for this framework [assembly: PexAssemblySettings(TestFramework = "MyUberTestFrameworkName")]
public static void AreElementsNotNull<T>(T[] value)
where T : class
{
PexAssume.NotNull(value);
// the followings prevents the exploration of all array lengths
int len = PexSymbolicValue.Ignore<int>(value.Length);
// building up a boolean value as follows prevents exploration
// of all combinations of non-null (instead, there are just two cases)
bool anyNull = false;
for (int i = 0; i < len; ++i)
anyNull |= value[i] == null;
// was any element null?
if (anyNull)
PexAssume.Fail("some element of array is a null reference");
}
public sealed class Key {
public int Value;
public override int GetHashCode() { return this.Value; }
public override bool Equals(object obj) { return obj is Key && ((Key)obj).Value==this.Value; }
}
public enum Action { Add, Remove }
[PexMethod]
public void HashtableAddRemoveTest()
{
IPexOracleSession s = PexChoose.DefaultSession;
Hashtable h = new Hashtable();
int len = s.ValueFromRange("len", 0, 4);
int count = 0;
for (int i = 0; i < len; i++) {
switch (s.ChooseFrom("action", Action.Add, Action.Remove)) {
case Action.Add: {
Key k = s.ValueNotNull<Key>("addKey");
PexAssume.IsTrue(!h.Contains(k));
h.Add(k, new object());
PexAssert.IsTrue(h.Contains(k));
count++;
break;
}
case Action.Remove: {
Key k = s.ValueNotNull<Key>("removeKey");
PexAssume.IsTrue(h.Contains(k));
h.Remove(k);
PexAssert.IsTrue(!h.Contains(k));
count--;
break;
}
}
}
PexAssert.AreEqual(h.Count, count);
}
...
void AppendFormat(IFormatProvider provider, String format, params Object[] args) {
if (format == null || args == null) {
throw new ArgumentNullException((format == null) ? "format" : "args");
}
char[] chars = format.ToCharArray(0, format.Length);
int pos = 0;
int len = chars.Length;
char ch = '\x0';
ICustomFormatter cf = null;
if (provider != null) {
cf = (ICustomFormatter)provider.GetFormat(typeof(ICustomFormatter));
}
...
class PFormatProvider : IFormatProvider {
public object GetFormat(Type formatType) {
var chooser = PexChoose.FromCall(this);
return chooser.ChooseResult<object>();
}
}
[PexMethod]
public void TestAppendFormat(IFormatProvider formatProvider, string format, object[] args) {
var sb = new StringBuilder();
... AppendFormat(... formatProvider, format, args);
}
| InvalidCastException: Unable to cast object of type 'MFormatProvider' to type 'System.ICustomFormatter' |
var recorder = PexChoose.NewTest(); var mfp0 = new PFormatProvider(); recorder.OnCall(0, "MFormatProvider.GetFormat(Type)").Returns(mfp0); string s0 = ""; object[] os0 = new object[0]; this.TestAppendFormat(mfp0, s0, os0);
[PexMethod]
[PexAllowedException(typeof(ArgumentNullException))]
[PexAllowedException(typeof(FormatException))]
public string TestAppendFormat(string format, object[] args) {
var formatProvider = new PFormatProvider();
var sb = new StringBuilder();
StringBuilderWrapper.AppendFormat(sb, formatProvider, format, args);
return sb.ToString();
}
__Substitutions.
public class Foo {...}
public class Bar {...}
...
using Microsoft.Pex.Framework;
[TestClass]
[PexClass(typeof(Foo))]
// decorator attribute, applies to FooTest only
[PexCoverageFilterType(PexCoverageDomain.UserCodeUnderTest, typeof(FooHelper))]
public partial class FooTest
{...}
[TestClass]
[PexClass(typeof(Bar))]
// decorator attribute, applies to BarTest only
[PexCoverageFilterType(PexCoverageDomain.UserCodeUnderTest, typeof(BarHelper))]
public partial class BarTest
{...}
pex.exe /mode:unittest /settingsassembly:MySettings.dll myunittests.dll
// settings assembly, where MyUserAssembly.dll is the assembly under test.
[assembly: PexInstrumentAssembly("MyUserAssembly")] // make sure it is instrumented
[assembly: PexCoverageIncludeAssembly("MyUserAssembly")] // get some coverage data for MyUserAssembly
[assembly: PexUserAssembly("MyUserAssembly")] // useful to filter out ArgumentException issues
// injecting exception on field write
[assembly: PexInjectsExceptionOnWrite]
for (int i=0; i<100; i++) { }
[PexMethod(MaxBranches=int.MaxValue)]
public void MyTest(...) {
// ....
}
for (int i=0;
PexSymbolicValue.Ignore(i<100); // Pex will 'forget' about this path condition
i++)
{ }
[PexMethod(MaxCalls=int.MaxValue)]
public void MyTest(...) {
// ....
}
[PexMethod]
void ParameterizedTest(int n) {
// conditions are "0<n", "1<n", ..., "!(n<n)"
for (int i=0; i<n; i++)
{ ... }
// irrelevant for MaxConditions, since conditions do not depend on input
for (int i=0; i<100; i++)
{ ... }
}
[PexMethod(MaxConditions=10000)]
void ParameterizedTest(int n) {
// ...
}
[PexMethod]
void ParameterizedTest(int n) {
int nshadow = PexSymbolicValue.Ignore(n); // Pex looses tack of 'n'
// irrevelant for MaxConditions, since nshadow is not related to input
for (int i=0; i<nshadow; i++)
{...}
}
pex.exe /testp:myproject.csproj ...
pex.exe /testp:myproject.csproj /testpnew:myproject.csproject ...
pex.exe ... /testcp

public class Outerclass
{
public class Innerclass
{
public int Field;
}
}
public class Outerclass
{
// not public!
class Innerclass
{
public int Field;
}
}
[TestMethod]
[PexInjectedException(typeof(ThreadAbortException), "OnWrite")]
...
public void SomeGeneratedTest() {...}
public class Foo {
public void Bar(int i) { ... }
}
[PexMethod]
public void Bar([PexAssumeUnderTest]Foo target, int i) {
target.Bar(i);
}
[PexMethod(MaxStack=int.MaxValue)]
public void MyTest(...) {
// ....
}
[PexMethod(MaxRuns=2000)]
void ParameterizedTest(int n) {
// ...
}
[PexMethod(MaxRunsWithoutNewTests=2000)]
void ParameterizedTest(int n) {
// ...
}
regsvr32 ...\Pex\bin\Microsoft.ExtendedReflection.ClrMonitor.x86.dll
| Read the chapter on Instantiating Existing Classes to learn how to help Pex in constructing interesting objects. |
[PexMethod]
[PexUseType(typeof(System.Collections.Hashtable))]
public void MyTest(IDictionary[] dictionaries) { ... }
[assembly: PexUseType(typeof(System.Collections.Hashtable))]
| Read the chapter on Instantiating Existing Classes to learn how to help Pex in constructing interesting objects. |
[PexClass(typeof(MyTypeUnderTest))]
public class MyTestClass { ... }
[PexClass]
public class BadFoo
{
private BadFoo() // Constructor not visible!
{...}
}
[PexClass]
internal class InternalFoo {} // type not exported!
[PexClass]
public abstract AbstractFoo {} // abstract type!
| Note: In addition to adding a reference to a unit test framework, you must actually use some type from it. If you don't, the C# compiler silently removes the reference! For example, to keep the reference alive, tag the PexClassAttribute with a TestClassAttribute attribute. |
public static TriangleKind Classify(int s1, int s2, int s3)
{
if ((s1 == s2) && (s2 == s3) && (s1 == s3))
return TriangleKind.Equilateral;
if ((s1 + s2 <= s3) || (s1 + s3 <= s2) || (s2 + s3 <= s1))
return TriangleKind.Invalid;
if ((s1 == s2) || (s2 == s3) || (s1 == s3))
return TriangleKind.Isosceles;
if ((s1 != s2) && (s2 != s3) && (s1 != s3) && (s1 + s2 > s3) && (s1 + s3 > s2) && (s2 + s3 > s1))
return TriangleKind.Scalene;
return TriangleKind.Invalid;
}
[TestClass, PexClass]
public partial class TriangleTest
{
[PexMethod]
public void TestTriangle(int s1, int s2, int s3)
Triangle.Classify(s1, s2, s3);
}
}
[assembly: PexInstrumentType(typeof(Triangle))]
PexAssume.IsTrue(s1 > 0 & s2 > 0 & s3 > 0);
public static class QuickSort
{
public static void Sort(int[] szArray, int nLower, int nUpper);
}
[PexMethod]
public void TestQuickSort([PexAssumeNotNull] int[] a)
{
QuickSort.Sort(a, 0, a.Length - 1);
for (int i = 0; i < a.Length - 1; i++)
PexAssert.IsTrue(a[i] <= a[i + 1]);
}
[PexMethod(MaxRuns=50)]
Expr ::= IDENT
| NUMBER
| "let" Ident = Expr "in" Expr
| Expr + Expr
| Expr - Expr
1 a 1+a 2 - 4 + b let x = 1 in 1 + x
public enum Operator { Add, Sub }
abstract public partial class Expression {}
public partial class Constant : Expression {
public int Value;
}
public partial class Binary : Expression {
public Operator Operator;
public Expression Left;
public Expression Right;
}
public partial class Let : Expression {
public string Name;
public Expression Definition;
public Expression Body;
}
public partial class Var : Expression {
public string Name;
}
public partial class Constant : Expression {
public override string ToString() {
return this.Value.ToString();
}
}
public partial class Binary : Expression {
public override string ToString() {
return string.Format("({0}{1}{2})",
this.Left,
this.Operator == Operator.Add ? "+" : "-",
this.Right);
}
}
public partial class Let : Expression {
public override string ToString() {
return string.Format("(let {0}={1} in {2})", this.Name, this.Definition, this.Body);
}
}
public partial class Var : Expression {
public override string ToString() {
return string.Format("{0}", this.Name);
}
}
abstract public partial class Expression
{
public static bool IsWellformed(Expression e)
{
return IsWellformed(new Dictionary<Expression, bool>(), e);
}
public static bool IsWellformed(Dictionary<Expression, bool> visited, Expression e)
{
if (e == null) return false;
if (visited.ContainsKey(e)) return false; // cycle
visited.Add(e, true);
bool res = e.GetInternalIsWellformed(visited);
visited.Remove(e);
return res;
}
public static bool IsWellformed(string s)
{
return !String.IsNullOrEmpty(s);
}
protected abstract bool GetInternalIsWellformed(Dictionary<Expression, bool> visited);
}
public partial class Constant : Expression
{
protected override bool GetInternalIsWellformed(Dictionary<Expression, bool> visited)
{
return true;
}
}
public partial class Binary : Expression
{
protected override bool GetInternalIsWellformed(Dictionary<Expression, bool> visited)
{
return
(this.Operator == Operator.Add | this.Operator == Operator.Sub) &&
IsWellformed(visited, this.Left) &&
IsWellformed(visited, this.Right);
}
}
public partial class Let : Expression
{
protected override bool GetInternalIsWellformed(Dictionary<Expression, bool> visited)
{
return
IsWellformed(this.Name) &
IsWellformed(visited, this.Definition) &&
IsWellformed(visited, this.Body);
}
}
public partial class Var : Expression
{
protected override bool GetInternalIsWellformed(Dictionary<Expression, bool> visited)
{
return IsWellformed(this.Name);
}
}
abstract public partial class Expression {
public static bool IsClosed(Expression e) {
return e.GetInternalIsClosed(new Dictionary<string, bool>());
}
protected internal abstract bool GetInternalIsClosed(Dictionary<string, bool> names);
}
public partial class Constant : Expression {
protected internal override bool GetInternalIsClosed(Dictionary<string, bool> names) {
return true;
}
}
public partial class Binary : Expression {
protected internal override bool GetInternalIsClosed(Dictionary<string, bool> names) {
// Closed(Left) and Closed(Right)
return this.Left.GetInternalIsClosed(names) & this.Right.GetInternalIsClosed(names);
}
}
public partial class Let : Expression {
protected internal override bool GetInternalIsClosed(Dictionary<string, bool> names) {
// Closed(Definition, names) and Closed(Body, names + {Name})
if (!this.Definition.GetInternalIsClosed(names)) return false;
bool contained = names.ContainsKey(this.Name);
if (!contained)
names.Add(this.Name, true);
bool res = this.Definition.GetInternalIsClosed(names);
if (!contained)
names.Remove(this.Name);
return res;
}
}
public partial class Var : Expression {
protected internal override bool GetInternalIsClosed(Dictionary<string, bool> names) {
return names.ContainsKey(this.Name);
}
}
for (int i=0; i<100; i++) { }
[PexMethod]
void ParameterizedTest(int n)
{
for (int i=0; i<n; i++) { // conditions are "0<n", "1<n", ..., "!(n<n)"
...
}
for (int i=0; i<100; i++) { // irrelevant for MaxConditions, since conditions do not depend on input
...
}
}
abstract class FooAttributeBase : Attribute
{
abstract void DoSomething();
}
class MyFooAttribute : FooAttributeBase
{
override void DoSomething() { Console.WriteLine("hello"); }
}
...
[MyFoo]
class Bar {}
foreach(FooAttributeBase attribute in
Attribute.GetAttributes(typeof(FooAttributeBase), typeof(Bar)))
{ Console.WriteLine(attribute); }
-- output
MyFooAttribute
[assembly: PexAssumeFailedException(typeof(MyException))]
Debug.Assert(this.foo > 0);
private void PrivateMethod(string s)
{
Debug.Assert(s != null);
...
}
public void PublicMethod(string s)
{
if (s == null)
throw new ArgumentNullException(s);
...
}
[Test]
public void SomeTest(string s)
{
PexAssume.IsNotNull(s);
}
if (!c) throw new ArgumentException(...);
if (c==null) throw new ArgumentNullException(...);
if (!c) throw new InvalidOperationException(...);
| (c) Microsoft Corporation. All rights reserved. | pex Wiki Documentation 0.16.40915.5 |