InnoTech Presentations Posted
The presentations from the InnoTech PDX conference I spoke at have been posted. You can get my “Unit Testing with Typemock” presentation as well as the demo code from there.
The presentations from the InnoTech PDX conference I spoke at have been posted. You can get my “Unit Testing with Typemock” presentation as well as the demo code from there.
Based on my previous all-in-one experience with the HP C7280, when I brought the Canon PIXMA MX850 home, the first thing I did after I installed it was to try out a scan. I didn’t print, I didn’t copy, I just scanned.
Freaking garbage.
Not as bad as the HP C7280, mind you, but still pretty bad. I tried a book cover and two different CD covers. All of them came out with horrible Moire patterns and pixel artifacts.
I never printed a single page (other than the printer head calibration). It’s already in the box to be taken back.
I’ve learned something, but I’m not sure what.
Anyway, back to square one.
I’m a Twitter user, but it wasn’t always like that. The problem is, Twitter really only seems to be useful if you have a Twitter client. The web site interface they provide is cumbersome, and if you’ve only used it over SMS or IM, you’re missing out on a far richer experience.
I started out using Snitter and really liked it, but there were a few features missing (like the ability to follow someone right from the client) that I wanted, so I tried twhirl. It’s pretty cool. The only thing I didn’t like about it is that you have to customize the defaults a bit to really get the most out of it. Here’s what you have to do to get the most from twhirl:
Turn off “prefix tweets with sender’s name.” This is in the configuration, on the “Visual” tab. The sender’s name already appears in some smaller meta-text below each post, so prefixing the tweets with the sender’s name just eats up screen space.
Turn off “mark received tweets as new.” This is also in the configuration, on the “Visual” tab. Unless you follow less than 10 people or you have more time on your hands than you know what to do with, you’re probably not going to be reading Twitter the same as you read email. Twitter is like standing in a convention hall where everyone is talking to everyone else. You’ll probably miss some tweets, you might hear bits and pieces of a conversation, and that’s OK. Turning this option off will stop you from seeing an annoying little “light” on each tweet you haven’t read.
Set the opacity to 100% when inactive. Again, in the configuration, on the “Visual” tab. It’s really annoying to have a 65% opaque window scrolling tweets when you’re doing something else. It’s like seeing something in your peripheral vision that you can’t quite get to focus. Turn this up to 100% so there’s something concrete to glance over to when you’re working on something else.
Customize your color scheme. This can be as easy or as difficult as you want it. The default aqua sort of color scheme is just painful. You can very easily select a new color scheme from the Accounts window on the “Colors” tab. I recommend one of the black schemes, but check it out and you can see a little preview image of each one and choose your own.
The other option you have is to create your own color scheme. As of version 0.7.5, this isn’t an “officially supported option,” but it’s still simple.
To create your own scheme:
When I created my custom scheme, I wanted to address the following issues:
My custom scheme looks like this:
And you can download it here if you like. (Unzip the file into your twhirl colorschemes directory. The XML file inside is the color scheme.)
Overall, twhirl is pretty good. Snitter is a little better from a style flexibility perspective, and if it gets updated to have some of the features I like, I’ll probably switch back. On the other hand, if twhirl can give me some additional style flexibility, I’ll be totally won over.
I
play fake
drums
in Rock
Band
and have a great time with it. Problem is, my dining room chairs aren’t
great for drumming. They’re a little low and generally bulky compared to
what I need when I’m rocking out. I ended up finding the “Vitamin”
stool at Ikea and
it’s perfect.
Plus, it’s pretty reasonably priced. If you’re looking for a good drummer stool, grab yourself one of these.
This quick start gets you up to speed on the basic functionality of Typemock Isolator. As you go through it, note:
At the very end are some take-away points and additional resources. Work through the quick start, do the exercises, and at the end check out the take-away points so you’ll have something to move forward with.
You can get the source for the finished solution here (minus the answers to the exercises - that’s for the reader), but it’s recommended you create your solution and walk through the work and not just get the finished deal: [View Complete Source]
You’ll need to have the following to work through the quick start:
Visual Studio 2008, Typemock Isolator, and TestDriven.NET get installed on your local developer machine. NUnit should be in an accessible location but doesn’t necessarily have to be installed. Get the latest available versions.
You’ll need a place where you can run through these exercises, so…
This section discusses basic patterns you’ll need to understand while working with unit testing and mocking.
The basic pattern for a unit test is “Setup, Execute, Assert”:
To examine this pattern, set up a simple class that can be tested and perform some unit tests on it.
Calculator
. Make it public.Calculator
class, add a method with this signature that
adds two doubles (a + b): public double Add(double a, double b)
Calculator.Add
method.Calculator
class, add a method with this signature that
divides two doubles (a / b):
public double Divide(double a, double b)
Calculator.Divide
method. If “b” is zero,
throw a DivideByZeroException
.Now you have a simple class to test, let’s add a test fixture for it.
CalculatorFixture
. Make it public.[TestFixture]
attribute to CalculatorFixture
. This
is how you tell NUnit and TestDriven.NET that this class contains
unit tests.You now have a class to test and a fixture to contain your tests. Add a
test for the Calculator.Add
method.
public void
method that takes no
parameters called “AddTwoPositiveNumbers”:
public void AddTwoPositiveNumbers()
[Test]
attribute to the AddTwoPositiveNumbers
method. This is how you tell NUnit and TestDriven.NET that this is a
test to run.Your test fixture will look something like this:
[TestFixture]
public class CalculatorFixture
{
[Test]
public void AddTwoPositiveNumbers()
{
// Setup
Calculator calc = new Calculator();
// Execute
double result = calc.Add(3, 7);
// Assert
Assert.AreEqual(10, result);
}
}
Add more tests.
Add
method:
Divide
method:
[ExpectedException]
attribute on your test method).Notice how the pattern is basically the same? You do some initialization, run some code, and assert that the result is what you expected. You see a slight deviation from that pattern when testing for expected exceptions, but it’s still basically doing an assertion, just expressed differently.
The basic pattern for mocking an object is “Record, Playback, Verify”:
This parallels the unit test “Setup, Execute, Assert” pattern. Part of your setup is to record your mocks; part of execution is playing back your mocks; part of assertion is verifying your mocks.
Add a new method to the Calculator
class that has additional
complexity. We’ll use mocking to test this method:
public double AddThenMultiply(double a, double b, double c)
{
double addResult = this.Add(a, b);
double multiplyResult = addResult * c;
return multiplyResult;
}
Notice in this method that we’re calling the Add
method (which we’ve
already tested) and performing some additional custom logic that we need
to test. This sort of thing is perfect for mocking. We don’t want to
re-test the Add
method; we want to isolate the logic in the new method
and just test that. Let’s add a new fixture with tests that use Typemock
Isolator to isolate the new logic.
CalculatorMockingFixture
. Make it public.[TestFixture]
attribute to
CalculatorMockingFixture
.[VerifyMocks]
attribute to
CalculatorMockingFixture
. This tells Typemock Isolator to
automatically do the mock verification part of the test for you when
the test is complete. It saves you from having to manually verify in
every test.The empty fixture should look like this:
[TestFixture]
[VerifyMocks]
public class CalculatorMockingFixture
{
}
Now we’re ready to add a test. In the CalculatorMockingFixture
add a
test method called MultiplyPositiveAddResult
. Here is the method body:
[Test]
public void MultiplyPositiveAddResult()
{
Calculator calc = new Calculator();
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
double dummy = calc.Add(0, 0);
recorder.Return((double)15);
}
double result = calc.AddThenMultiply(5, 10, 20);
Assert.AreEqual(300, result);
}
There’s a lot happening here, so let’s look over it:
Calculator
object we’re going to test gets instantiated.using
block is created where a new RecordExpectations
object
is created. This is a very common block you will see in Typemock
Isolator usage that says, “Everything in this block is fake! Record
it and get ready to play it back.” Inside that block…
Add
method on the Calculator
. Notice that
we’re passing 0 for both parameters. The reason for this is that
the Add
method really isn’t getting called, so it doesn’t
matter what we pass. The important part of this is that we’re
telling the recorder, “I’m going to call the Add
method.” We
don’t even really care what we name the variable where we store
the result because we’ll never use it - hence, we’ll just call
it “dummy.”Add
to return - in this
case, we want it to return 15. We don’t care what gets passed
in, the first time Add
gets called, we want 15 to come back.using
block closes, meaning we’re done recording for now. Time
for playback.AddThenMultiply
method and get the result.What did mocking get us? Try this: change this line:
double result = calc.AddThenMultiply(5, 10, 20);
To this:
double result = calc.AddThenMultiply(500, 1000, 20);
Now run the test again. Notice how it still passes? Why is that? That’s
mocking in action. If you follow the call stack, you know that the first
thing the AddThenMultiply
method does is call the Add
method.
Typemock Isolator sees that call to Add
and doesn’t actually let Add
execute - instead, it returns the value we told it to return. In this
case, we’ll get 15 back.
Do some experimentation…
Add
a second time in your test? Try
adding a call to calc.Add
after the AddThenMultiply
call.Add
but 25 for the second call?Once you’ve gotten your first mock down and get the patterns, the next
question is, “How can I actually use this in my job? I’m not writing
Calculator
classes all day.” The benefit of mocking is to isolate the
code that you’re testing - that includes isolating it from the behavior
of the .NET framework and other third-party dependencies. In this
section you’ll walk through an example of isolating your code from .NET
proper and look at some additional mocking verification that can be done
to ensure your code is calling the framework correctly.
To experiment with isolation from .NET, we’ll add a new class. This class will make use of the .NET configuration system to read a value from configuration and perform an action based on that.
System.Configuration
assembly.ConfigReader
. Make it public.public
method called AppendValueToSetting
that takes in a
string
and returns a string
:
public string AppendValueToSetting(string valueToAppend)
AppendValueToSetting
method:
AppSettings
key “configReader” and store the result.valueToAppend
parameter to the end
of the value from configuration.It should look like this:
public class ConfigReader
{
public string AppendValueToSetting(string valueToAppend)
{
string setting = ConfigurationManager.AppSettings["configReader"];
string result = setting + valueToAppend;
return result;
}
}
Consider what you need to test about this method:
Now consider: It reads from the App.config
file - how do you change
that between tests? Is that even a good idea?
Again - mocking to the rescue.
ConfigReaderFixture
and include both the [TestFixture]
attribute
and [VerifyMocks]
attribute.SettingFound
- we’ll test
what happens when the setting is correctly read from configuration.ConfigReader
.ConfigurationManager.AppSettings["configReader"]
key.AppendValueToSetting
method and pass in
“PassedInFromTest”.The test will look like this:
[Test]
public void SettingFound()
{
ConfigReader reader = new ConfigReader();
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
string dummySetting = ConfigurationManager.AppSettings["configReader"];
recorder.Return("readFromAppSettings");
}
string result = reader.AppendValueToSetting("PassedInFromTest");
Assert.AreEqual("readFromAppSettingsPassedInFromTest", result);
}
Notice how you didn’t actually have to put anything in App.config
-
you don’t really want to re-test the functionality of the .NET
framework, you just want to test that your code is correct.
Take this to the next step…
Try this: Go to your ConfigReader
class and modify this line:
string setting = ConfigurationManager.AppSettings["configReader"];
To be this:
string setting = ConfigurationManager.AppSettings["theWrongKey"];
Now run your tests - they all still pass. Why?
As mentioned earlier, Typemock Isolator will, by default, just notice which methods and properties you’re using, not what the values of parameters are. Sometimes you’ll want to make sure that not only does the third-party dependency return an expected/recorded result but also that your code is passing in the proper parameter values. In this case, you want to not only make sure that you’re getting an expected value from the configuration system but also that your code is asking for the value you think it’s asking for. You’ll want the recorder to “check arguments.”
Leave the wrong config key in your ConfigReader
class - we’ll catch
that it’s wrong inside the unit tests.
In the SettingFound
test, in your recorder block immediately after the
call to ConfigurationManager.AppSettings
, tell the recorder to check
arguments:
[Test]
public void SettingFound()
{
ConfigReader reader = new ConfigReader();
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
string dummySetting = ConfigurationManager.AppSettings["configReader"];
recorder.CheckArguments();
recorder.Return("readFromAppSettings");
}
string result = reader.AppendValueToSetting("PassedInFromTest");
Assert.AreEqual("readFromAppSettingsPassedInFromTest", result);
}
That tells the recorder that you want to ensure the arguments in the
mocked statement are correct. In this case, the argument is the string
“configReader” that gets passed to ConfigurationManager.AppSettings
.
Now run the tests: The SettingFound
test fails with an exception like
this:
TestCase 'TypeMockQuickStart.ConfigReaderFixture.SettingFound'
failed: Typemock Isolator.VerifyException :
Typemock Isolator Verification: Call to System.Collections.Specialized.NameValueCollection.get_Item() Parameter: 1
expected: <"configReader">
but was: <"theWrongKey">
Typemock Isolator caught that the wrong parameter was passed - the one
in the test (“configReader”) was expected, but your production code used
the wrong value (“theWrongKey”). Fix the ConfigReader
class back to
the correct settings key and your test will pass again.
Once you get past the simplest of cases, you start needing to mock specific instances of classes and sometimes you need to mock methods on instances that get created inside non-test code. Typemock Isolator can do both of these things.
This exercise will show you how to create an instance of an object where the constructor of the object is mocked and you control the entire life of that object.
Add a new class to your project. This class will use the Calculator
class you added earlier. First, add a couple of constructor overloads to
your Calculator
class:
public class Calculator
{
private bool _allowAdd;
public Calculator() : this(true) { }
public Calculator(bool allowAdd)
{
this._allowAdd = allowAdd;
}
// Add, Divide, and AddThenMultiply methods omitted for clarity.
}
Now update the Calculator.Add
method so if the _allowAdd
member
variable is false
, the Add
method won’t run:
public double Add(double a, double b)
{
if (!this._allowAdd)
{
throw new InvalidOperationException("Add operation is not allowed.");
}
return a + b;
}
Running your tests, they should all still pass. Notice the default value
for allowing the Add
operation is true
and it’s set in the default
constructor. Now in your CalculatorMockingFixture
test fixture, add a
new test:
[Test]
public void SkipConstructor()
{
Calculator calc;
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
calc = new Calculator();
}
calc = new Calculator();
double result = calc.Add(2, 2);
Assert.AreEqual(4, result);
}
This test runs the constructor for the object inside the recorder block - that means the constructor itself will be mocked. In this case, think
about what that means - the default value for an uninitialized Boolean
is false
, so the _allowAdd
value, which normally gets initialized to
true
in the default constructor, will remain false
and won’t let the
Add
operation run.
Run the test and the test will fail:
TestCase 'TypeMockQuickStart.CalculatorMockingFixture.SkipConstructor'
failed: System.InvalidOperationException : Add operation is not allowed.
You can fix the test so it passes by adding an [ExpectedException]
attribute to the test and expecting an InvalidOperationException
.
Usually constructor logic is more complex than this - it might read from configuration, try to initialize a file in the filesystem, or do some other actions that you may want to control. In cases like these, you may need to mock the constructor for the object.
Add a test where you mock the constructor logic but also test the
AddThenMultiply
method. What does that look like? How does it differ
from the original test you ran with AddThenMultiply
?
This exercise will show you how to set up expectations on an object that gets created in code you don’t control.
Add a new class called BackwardsCalculator
to your project. The
constructor of the BackwardsCalculator
class will create an instance
of Calculator
and hang onto it. A method ReverseAdd
will perform an
add operation using the Calculator
and reverse the string value of
that. The BackwardsCalculator
class looks like this:
public class BackwardsCalculator
{
private Calculator _calculator;
public BackwardsCalculator()
{
this._calculator = new Calculator();
}
public string ReverseAdd(double a, double b)
{
string forward = this._calculator.Add(a, b).ToString();
string reversed = new string(forward.ToCharArray().Reverse().ToArray());
return reversed;
}
}
If you feed in 10 and 25 to the ReverseAdd
method, you’ll get “53”
returned: 10 + 25 is 35, reverse 35 is 53.
Notice how the BackwardsCalculator
constructor is creating a
Calculator
but you don’t get a chance to insert a mock yourself.
That’s okay - you can still use mocks to mock out the call to
Calculator.Add
so you’re isolating your code.
BackwardsCalculatorFixture
and include both the [TestFixture]
attribute and [VerifyMocks]
attribute.ReverseAddPositive
- we’ll
test two positive inputs.Calculator
class.Add
operation and pass in two known values.Add
operation to make sure
you’re getting called with the expected parameters.BackwardsCalculator
.ReverseAdd
method and pass in the parameters you
decided on in the record block.The test will look something like this:
[Test]
public void ReverseAddPositive()
{
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
Calculator dummyCalc = new Calculator();
dummyCalc.Add(10, 20);
recorder.CheckArguments();
recorder.Return((double)30);
}
BackwardsCalculator bCalc = new BackwardsCalculator();
string result = bCalc.ReverseAdd(10, 20);
Assert.AreEqual("03", result);
}
By adding the constructor call to the mock recorder block, we’re saying,
“Mock the next instance of this object that gets created and set these
expectations on that object.” When we instantiate the
BackwardsCalculator
after the recorder block, the mocking framework
goes into playback mode and mocks the creation of the Calculator
in
the BackwardsCalculator
constructor.
Add
was doing more than just adding, this would be perfect for
isolating our code. Add is a simple method, though. Look at the
CallOriginal
method on the recorder and see if you can get a test
to pass where you’re checking arguments but actually calling a live
version of the Calculator.Add
method.ReverseAdd
method is using LINQ to reverse the string. Try
mocking the LINQ Reverse
or ToArray
statements.WhenArgumentsMatch
method on the recorder. It lets you
conditionally mock a statement based on the arguments that get
passed into a method. Can you set up the mock so it only runs when
the arguments match what is getting passed in?Mocking lets you isolate yourself from a lot of common situations, including:
There are other cases where you might need to use Typemock Isolator, too, like adding tests for an API that was already written and can’t change. You can mock lots of things that can make testing tricky…
If you forget everything else, remember these rules of thumb:
The Typemock Learn page has a great set of resources, including:
The Cheat Sheets are particularly helpful - one-page references you can print off and use while you’re working.
If you use Snippet Compiler, you can experiment with Typemock Isolator using a special template for Snippet Compiler.