I've got one more test scenario for Pex. From comments on my previous post
Case study 3 I understood that the way I specified the PUT was not done correctly (though Pex generated the unit test methods I expected).
A PUT should specify what the intended behaviour of the code under test should do. It should not do this like in a tradiotional unit test for a particular combination of test input but in a more general way.
Sounds reasonable but I find some difficulity in writing them. I'll try to come with a "better" PUT this time.
Our code under test is as follows (Sorry in advance for some bad formatting HTML tables later in the post.):
private string mCode;
public string Code
{
get { return mCode; }
set {
if (value == null )
{
throw new System.ArgumentNullException("Please specify a valid code. (non-null)");
}
else if (value.Length < 4)
{
throw new System.ArgumentException("Please specify a valid code. (bigger than 3 characters.");
}
else if (value.Length > 10)
{
throw new System.ArgumentException("Please specify a valid code. (max 10 characters. including XYZ prefix) ");
}
else if (value.StartsWith("XYZ") == false)
{
throw new System.ArgumentException("Please specify a valid code (starting with XYZ - uppercase !) ");
}
else
{
this.mCode = value;
}
}
With the comments for my PUT in mind , I created the following PUT:
[PexMethod()]
public void CodeTest(string aCode)
{
measurement target = new measurement();
string actual;
target.Code = aCode;
actual = target.Code;
PexValue.AddForValidation("actual", actual);
if (( aCode != null) &&
(aCode.Length > 3) &&
(aCode.Length <= 10) &&
(aCode.StartsWith("XYZ")) )
PexAssert.IsTrue(actual == aCode);
}
Running Pex on this PUT will result in several generated test cases.
(Pex reporting option : Enable via Options/Pex/Reports)
| Parameter Values | |||
|---|---|---|---|
| Run | aCode | actual | Summary/Exception |
| 1 | null | ArgumentNullException: Value cannot be null.(testingPEX) | |
| 2 | "" | ArgumentException: Please specify a valid code. (bigger than 3 characters. (testingPEX) | |
| 3 | \0\0\0\0\0\0 | ArgumentException: Please specify a valid code (starting with XYZ - uppercase !) (testingPEX) | |
| 4 | new string('\0', 14) | ArgumentException: Please specify a valid code. (max 10 characters. including XYZ prefix) (testingPEX) | |
| 5 | XYZZZZZ | XYZZZZZ | |
Of course we first need to specify the expected exceptions (Pex will suggest these for you !) :
- Add attribute [PexAllowedExceptionFromAssembly(typeof(ArgumentNullException), "testingPEX")]
- Add attribute [PexAllowedExceptionFromAssembly(typeof(ArgumentException), "testingPEX")]
The generated unit tests look like this :
public partial class measurementTest
{
[TestMethod]
[PexGeneratedBy(typeof(measurementTest))]
public void CodeTestString_20080728_141020_005()
{
PexValue.Generated.Clear();
this.CodeTest("XYZZZZZ");
PexValue.Generated.Validate("actual", "XYZZZZZ");
}
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
[PexGeneratedBy(typeof(measurementTest))]
public void CodeTestString_20080728_143541_000()
{
this.CodeTest((string)null);
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
[PexGeneratedBy(typeof(measurementTest))]
public void CodeTestString_20080728_143620_001()
{
this.CodeTest("");
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
[PexGeneratedBy(typeof(measurementTest))]
public void CodeTestString_20080728_143620_002()
{
this.CodeTest("\0\0\0\0\0\0");
}
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
[PexGeneratedBy(typeof(measurementTest))]
public void CodeTestString_20080728_143620_003()
{
this.CodeTest(new string('\0', 14));
}
}
If you would verify the code coverage results in Visual Studio or via the Pex reporting option, you would see 100% Block coverage.
Pex generated for us the strings to serve as input values. I don't know about you but I think this is pretty clever.
Still I'm a little confused about the PUT I created. If I would delete all the pexAssert statements the exercise would still be the same for the generated unit tests.
[PexMethod()]
public void CodeTest(string aCode)
{
measurement target = new measurement();
string actual;
target.Code = aCode;
actual = target.Code;
PexValue.AddForValidation("actual", actual);
}
Thanks for reading.
Best regards,
Alexander
2 comments:
Here's a better way to write the PUT
[PexMethod]
public void TestCode(string code)
{
var target = new Measurement();
target.Code = code;
// target.Code invariant
Assert.IsTrue(target.Code != null);
Assert.IsTrue(target.Code.Length >= 4);
Assert.IsTrue(target.Code.Length <= 10);
Assert.IsTrue(target.Code.StartsWith("XYZ"));
// at this point, the following should hold
Assert.IsTrue(code == target.Code);
}
(note that the first 4 assertions could be refactored as an invariant for the measurement class)
Another tip: Ctrl + A, Ctrl + C will copy the values of the parameter table into the clipboard in a CSV format. From there, you can easily paste it in your editor :)
Post a Comment