Ayende @ Rahien

It's a girl

Rhino Mocks 3.5 Design Decisions: Getting closer to conclusion

There has been an invaluable amount of discussion regarding the question I pose about the API design of Rhino Mocks 3.5. Jeremy Gray in particular has been helpful in making good suggestions and making the argument to simplify the API for developers who are not experts in TDD terminology and usage.

My current thinking is to combine GenerateMock() and GenerateStub() into a single method, GenerateTestDouble(). This method will return a dynamic mock.

If you want a true stub, you will be able to call myTestDouble.StubUnexpectedInteractions(). Note, since stubs have a special behavior for properties, I am also considering: myTestDouble.StubPropertiesAndUnexpectedInteractions(); .

If you want a strict mock, you will be able to call myTestDouble.FailOnUnexpectedInteractions();

Partial mock will not be supported by the static GenerateTestDouble method, and will require using the usual instance methods.

Calling VerifyAllExpectations() will be supported on all mocks.

The only remaining open question is whatever calling Expect() on an object that you previously called StubUnexpectedInteractions() should fail or not.

Thoughts?

Batching WCF Calls

Several months ago I wrote about how I think you should design your services. The key criteria was that they have to have a batch mode enabled.

Afterward, I put together a screen cast that goes through all the stages that led me to that stage.

Davy Brion has taken this approach a bit further and posted all the infrastructure bits that are required to make this work as well as what you need to actually make the API almost as nice to use as the non batched version.

The service API is here and the client API is here.

About the only thing that I would strive to improve there would be the need to explicitly register request & replies. I would try to get something convention based there. Maybe something like Request<TRespose>, and then have IHandler<TRequest> and route the whole thing through the container again.

What hid under the bed...

public class ARValidatingAuthorizationRepository<TIEntityType, TIUsersGroup, TIEntitiesGroup, TIOperation, TIEntityReference, TIPermission>     
  :  RhinoAuthorizationRepository< TIEntityType, TIUsersGroup, TIEntitiesGroup, TIOperation, TIEntityReference, TIPermission> 
      where TIEntityType : class, IEntityType, new()
      where TIUsersGroup : class, IUsersGroup, new()
      where TIEntitiesGroup : class, IEntitiesGroup, new()
      where TIOperation : class, IOperation, new()
      where TIEntityReference : class, IEntityReference, new()
      where TIPermission : class, IPermission, new()

Rhino Mocks 3.5 Design Decisions: The role of Stub vs. Mock

Let us say that we have the following code that we want to test:

public void ForgotMyPassword(string username)
{
   var user = users.GetUserByName(username);
   user.HashedPassword = "new pass";
   users.Save(user);
}

One way to write the test is:

public void When_user_forgot_password_should_save_user()
{
    var mockUserRepository = MockRepository.GenerateMock<IUserRepository>();
    var stubbedSmsSender = MockRepository.GenerateStub<ISmsSender>();

    var theUser = new User{HashedPassword = "this is not hashed password"};    

    mockUserRepository.Stub(x => x.GetUserByName("ayende")).Return(theUser);

    mockUserRepository.Expect( x => x.Save(theUser) );

    var controllerUnderTest = new LoginController(mockUserRepository, stubbedSmsSender);

    controllerUnderTest.ForgotMyPassword("ayende");

    mockUserRepository.VerifyAllExpectations();
}

Another would be:

public void When_user_forgot_password_should_reset_password()
{
    var stubUserRepository = MockRepository.GenerateStub<IUserRepository>();
    var stubbedSmsSender = MockRepository.GenerateStub<ISmsSender>();

    var theUser = new User{HashedPassword = "this is not hashed password"};    

    stubUserRepository.Stub(x => x.GetUserByName("ayende")).Return(theUser);

    var controllerUnderTest = new LoginController(mockUserRepository, stubbedSmsSender);

    controllerUnderTest.ForgotMyPassword("ayende");

    stubUserRepository.AssertWasCalled( x => x.Save(user));
}

Again, we have the question of should we even allow asserts on stubs. But beyond that, consider this two tests, both are functionally the same. Thoughts?

Rhino Mocks 3.5 Design Decisions: To be strict or not?

Here is an interesting problem. What should this piece of code do?

var stubSmsSender = MockRepository.GenerateStub<ISmsSender>();
// test code
stubSmsSender.VerifyAllExpectations();

Right now this is a no-op.

But since stubs are explicitly not mocks, they shouldn't be verified. Should I throw here? For something which is a test design decision?

Rhino Mocks 3.5 Release Candidate

Well, after a much longer beta period, and getting some very valuable input, Rhino Mocks 3.5 is out in Release Candidate. I am putting this out as RC, but I am pretty sure that those bits would be the RTM version as well.

The only major task left is to start documenting the changes. The move to 3.5 has made a lot changes in approach that I recommend to use (note that the API is compatible with 3.4).

I would like to thank Jordan Terrell, David Tchepak, Stefan Steinegger, Jason Meckley, Scott Brady, Ernst Naezer, Roelof Blom and Aaron Jensen for helping me get this out the door.

The changes (from 3.4) are:

  • Assert Act Arrange syntax, of course.
  • Better handling of exception in raising events from mock objects
  • Fixing an issue with mock objects that expose methods with output parameter of type System.IntPtr.
  • Allowing to return to record mode without losing expectations.
  • Inline constraints:
  • [Test]
    public void WhenUserForgetPasswordWillSendNotification_WithConstraints()
    {
        var userRepository = MockRepository.GenerateStub<IUserRepository>();
        var notificationSender = MockRepository.GenerateStub<INotificationSender>();
    
        userRepository.Stub(x => x.GetUserById(5)).Return(new User { Id = 5, Name = "ayende" });
    
        new LoginController(userRepository, notificationSender).ForgotMyPassword(5);
    
        notificationSender.AssertWasCalled(x => x.Send(Arg.Text.StartsWith("Changed") ));
    }
  • CreateMock() is deprecated and marked with the [Obsolete] attribute. Use StrictMock() instead.
  • Fixed an issue with merging, would cause issues if you are also using Castle Dynamic Proxy.
  • Fixed various typos
  • Better error handling for AAA syntax abuse
  • Will give better errors if you call Verify on a mock that is in record mode.
  • BackToRecord extension method.
  • Can mock interfaces with modopt params.
    • If you don't know what this means, it means that you can now mock interfaces that C++/CLI generates under some conditions (mixing native types with CLR types). This is probably the longest standing bug in Rhino Mocks.
  • Fixed issue with mocking internal classes and interfaces.
  • Full XML documentation
  • New event raising syntax:
    eventHolder.Raise(stub => stub.Blah += null, this, EventArgs.Empty);
  • AAA syntax now works with Ordering
  • Better error message if trying to use SetupResult on stubbed mock properties.

There are a lot of goodies in this release.

I am starting to create the documentation for this release here. This is a wiki, any help would be appreciated.

You can get the new version, for both 3.5 and 2.0 from the download page.

On InternalsVisibleTo

Some people pointed out that the distinction between public and published can be done using InternalsVisibleTo. This is sort of possible, I agree, but it only works if you think about this as a unit testing measure.

Jon Skeet asked about good usages of InternalsVisibleTo aside from unit testing, and I decided to check and see what the framework is using it for. From cursory observation, it appears to be heavily misused. Just from observing the allowed dependencies make me cringe.

  • System.Data allows:
    • System.Data.Entity
    • SqlAccess
    • System.Data.DataSetExtensions
  • System.Web allows:
    • System.Web.Extensions
  • System.Xml allows:
    • System.Data.SqlXml
  • System.Data.SqlXml allows:
    • System.Xml <-- I don't want to know how they got this cycle
  • Microsoft.NETCF.Tools allows:
    • System.Web.Services <-- This one really scares me
  • Microsoft.Office.Tools.Common.v9.0 allows:
    • Microsoft.Office.Tools.Word.v9.0
    • Microsoft.VisualStudio.Tools.Office.Designer.Office2007
    • Microsoft.VisualStudio.Tools.Office.Designer.Office2007Tests
    • Microsoft.VisualStudio.Tools.Office.Outlook.UnitTests
  • Microsoft.Build.Conversion allows:
    • Microsoft.Build.Conversion.Unittest
  • Microsoft.Build.Engine allows:
    • Microsoft.Build.Engine.Unittest
  • PresentationCore allows:
    • System.Windows.Presentation
  • PresentationFramework allows:
    • PresentationFramework.Luna
  • System.Core allows:
    • Dlinq.Unittests <-- this is annoying, I don't get internals access to that, and I am also writing a linq provider
  • System.Design allows:
    • System.Web.Extensions.Design <-- well, if I want to write a designer, I have better work for MS...

Git to CodePlex

Well, it works, finally.

image

I had major issues getting commits to work. Eventually I figured out that git-svn does not send hashes of the files as all other SVN clients that I have tested so far. I was focused on finding corruption much earlier in the game, and drowned in the details.

I am not sure why it is committing a single change twice, but it is showing the same behavior on standard SVN servers, so I think that I am fine.

And here is the final test:

image

:-D

NMemcached: A WCF experiment

image

While doing a code review of NMemcached it started to bother me just how much of the application was infrastructure and argument parsing code. It shouldn't be this way. So I decided to port the whole thing to WCF and see how it works.

Porting it wasn't hard, and significantly reduced the amount of code in the application. After updating all the tests and verifying that I fixed all the things I broke, I built an appropriate memcache client and started perf testing again.

As a reminder, native Memcached server managed to field 10,000 reads and writes in just 1709.6 ms. My own implementation got to the same point in 3144.5 ms.

The WCF implementation (note, the implementation and the benchmark are different, because of the different approaches, but the test is the same)...

Right now it is using net.tcp binding and it is at a lousy 7853.3 ms.

The code is available here, and I would appreciate any comments. I didn't even try to optimize anything with WCF, just set it to net.tcp and let it handle everything else.

Public vs. Published

imageOne of the thing that you see some people agonizing about is what they should be exposed to the outside world. On the one hand, people have heard all about encapsulation, and how it is going to save the world. On the other hand, we want to expose functionality to the outside world, be it for testing or for advance usages of your software.

Something that I wish that C# had is the published alias to the public keyword, that would have expressed intent in a much easier fashion than just public.

That said, I found a very useful approach to handling this myself. Separating interface and implementation. Let us look at an example:

public interface ICommand
{
     void Init(string[] args);
     void Execute();
}

And an implementation of that:

public class MyCommand : ICommand
{
       public string Key { get; set; }
       public long ByteCount { get; set; }
 

       public void Init(string [] args)
       {
		// parse args to key & byte count
       }
}

Now, if I want to test that I am getting the right thing, I can, easily. At the same time, the published interface of this is ICommand, not whatever is public in MyCommand.

In situations where I have one to one mapping between interfaces and implementations (IUserRepository and UserRepository), this is even more pronounced.

ADO .NET Entity Framework Vote of No Confidence

I am a bit late on posting this, but I suggest taking a look here to read some of the community reactions to the issues we have observed in the Entity Framework.

I will let the document stand on its own, since there is no way I can be impartial here.

I would like to state something (which I also told the Entity Framework team in person):

If someone manages to come up with a kick ass OR/M solution that does what I need (allow me to create maintainable and flexible solutions and has the expendability points to be used on real world projects) and which I, personally, don't have to (help to) write, I would be utterly overjoyed.

Zero Friction: Creating a test model

I am writing some integration tests at the moment, using WatiN, and I am really enjoying the process. The last time that I tried to use WatiN it was in a WebForms environment, and it was... hard.

Using it with MonoRail is a real pleasure. Here is a simple test:

[Test]
public void Can_submit_new_values_for_webcast()
{
	browser.GoTo(appUrl + "webcast/edit/" + webcast.Id);
	var newTestName = "New test webcast name";
	browser.TextField("webcast_Name").Value = newTestName;
	var newDesc = "There is a new webcast description";
	browser.RichTextEditor("webcast_Description_Editor").Type(newDesc);

	browser.Button("webcast_save").Click();

	browser.Url.ShouldContain("webcast/view/" + webcast.Id);
	ReloadWebcastFromDatabase();
	webcast.Name.ShouldEqual(newTestName);
	webcast.Description.ShouldEqual(newDesc);
}

For a while, I was happy with this, but I have over two dozen such tests, and it is getting very annoying to remember what the all the names of all the fields are. The second time that I started copy & paste the ids from one test to another I knew that I had a big issue. How to solve this was something that I had to think about for a while, and then it came to me.

I can create a model for the interaction with the page, and test the UI through that. Here is my test model:

image Using that, I could get my test to look like this:

[Test]
public void Can_submit_new_values_for_webcast()
{
	browser.GoTo(appUrl + "webcast/edit/" + webcast.Id);
	var newTestName = "New test webcast name";
	edit.WebcastName.Value = newTestName;
	var newDesc = "There is a new webcast description";
	edit.Description.Type(newDesc);

	edit.Save.Click();

	browser.Url.ShouldContain("webcast/view/" + webcast.Id);
	ReloadWebcastFromDatabase();
	webcast.Name.ShouldEqual(newTestName);
	webcast.Description.ShouldEqual(newDesc);
}

Not that big deal, you may say, but now I can just blaze through those tests, writing them with far less friction along the way.

This is especially true when you modify the implementation of the page, but not the interaction, in this case, you want to be able to replace the implementation in a single place (say, change the id of a control, or the type of a control), instead of all over the place.

I am quite happy with this for now.

Bug of the day

This has caused some hair pulling, this piece of code fails if I don't pass a webcast variable, even though it is properly guarded.

image

Once I convinced myself that yes, I was stupid enough not to cover this scenario, reproducing this in a test was very easy.

The solution is so simple I am posting the changeset here:

image

My design process

Vijay Santhanam asks about the design process I takes for building:

How much analysis/OO modeling you do before you start writing real code? With tools like R#/SVN is the up-front design pretty much dead for garage projects?

My answer to that is complex. I don't do design. I don't think that I ever had. What I would do is something I call envisioning. I have posted several such things in the past, most recently it was Architecting Twitter.

A good way of describing that is this picture:

image

I am not really interested in the entire picture. I am interested in very small key parts of it. This foundation is what the entire application will revolve around. Very rarely I'll sit and try to draw out the entire system up front. And each and every time that I tried to do that I have had good reasons to regret it.

Once I identified the shape of the system, I I can start working on it. But the final result tend to be different than even the vague shape that I had at the beginning. I routinely modify the foundation of the system for the first part of the project, until it stable enough to fit what I want it to do comfortably.

I like to use tests and real use cases as the driving forces for this. A good sample of that can be seen with Rhino Security. I envisioned the system several months months before I actually wrote that, and while many of the high level concepts were retained, a lot of the infrastructure was shifted, as I faced real world constraints and had to solve them.

Why you should test code too silly to break

I wrote a test for this piece code:

public virtual void View([ARFetch("id")]Webcast webcast)
{
    PropertyBag["webcast"] = webcast;
}

Now, this looks like utter lunacy, isn't it? Especially when the test looks like:

[Test]
public void When_view_called_will_send_webcast_to_view()
{
	var webcast = new Webcast();
	controller.View(webcast);

	controller.PropertyBag["webcast"].ShouldBeTheSameAs(webcast);
}

Except that now that I have covered the very basic item, I now have another few tests:

[Test]
public void When_view_called_with_null_webcast_will_render_missing_webcast_view()
{
	controller.View(null);

	controller.SelectedViewName.ShouldEqual(@"Webcast\Missing");
}

[Test]
public void When_view_called_with_unpublished_webcast_will_render_unpublished_webcast_view()
{
	controller.View(new Webcast());

	controller.SelectedViewName.ShouldEqual(@"Webcast\Unpublished");
}

And the simplest thing that can make those test pass is:

public virtual void View([ARFetch("id")]Webcast webcast)
{
	if(webcast==null)
	{
		RenderView("Missing");
		return;
	}
	if(webcast.PublishDate==null)
	{
		RenderView("Unpublished");
		return;
	}
        PropertyBag["webcast"] = webcast;
}

By having tests from the beginning, even for trivial piece of code, I ensured both that the trivial case will work and that I am already starting with the right tone.

Deciding on the correct syntax for UI permissions

Going back to why I hate new projects, I am trying to figure out how to perform UI level security. Right now I need to dynamically decide whatever or not a user can edit a webcast. I came up with the following options.

Explicitly allow this for administrators only:

<% component adminOnly: %>
${ Html.LinkTo( "Edit", "webcast", "edit", webcast.Id) }
<% end %>

Allow this by operation:

<% component securedBy, {@operation: '/webcast/edit': %>
${ Html.LinkTo( "Edit", "webcast", "edit", webcast.Id) }
<% end %>

The second is much more flexible, but I am not sure that I am happy about putting the operation in the view.

I can create this, for that matter, which might be better all around, in which case this encapsulate everything inside it.

<% component edit, {@entity: webcast} %>

Thoughts?

My BDD experiment

I am trying to get BDD. As such, I started with building a list of specifications. Here is what I have so far. Now you get the chance to tell me why I am wrong...

As a user
I want to be able to see the latest webcast summary on the homepage
So that I have great visibility on what is new
-------------------
Acceptance criteria:
- Can see the name of the latest webcast
- Can see the date it was published
- Can read the short description
===============================================================
As a user
I want to be able to see the details of a webcast
So that I can see more details about the webcast
-------------------
Acceptance criteria:
- Can see the name of the latest webcast
- Can read the short description
- Can view number of downloads
- Can view relevant files
===============================================================
As a user
I want to be able to browse the archives of the site
So I can see old shows
-------------------
Acceptance criteria:
- Can see the names of all published webcasts
- Can click to the details of each webcast
- Can view number of downloads
- Can sort the list
===============================================================
As a user
I want to be able to subscribe to an RSS feed of the webcasts
So that I wouldn't have to check the site all the time
-------------------
Acceptance criteria:
- Each page on the site should have RSS link for news
- Publishing a new webcast would appear on the RSS
===============================================================
As an administor
I want to be able to add a new webcast
So that I can publish new webcasts
-------------------
Acceptance criteria:
- Can get to admin part of the site
- Can add a new webcast
- Will go through validation
- Can use rich text editor for the description
- Can set publish date
===============================================================
As an administrator
I want to be able to edit the details of an existing webcast
So that I can fix typos and change the data if I need to
-------------------
Acceptance criteria:
- Requires login
- Goes through validation
- Will update the RSS feed
===============================================================
As an administrator
I want to be able to login to the site
So that I can perform administrative functions
-------------------
Acceptance criteria:
- Requires login
- Unauthenticated users cannot login
- Non administrators cannot login
- Passwords are not kept in the clear
===============================================================

New project blues

I hate starting new projects.

I realize that this is a fairly uncommon opinion. Most developers that I have met loved going into new projects, starting from a blank slate. I dislike it, because early on in a project, there are all too many things that are still moving. There is a big amount of work that needs to be done before you can see real results.

Here is a typical graph for the time per feature.

image

The first steps are the most frustrating ones. You work for a long while before you can say that you have something that is really worth showing.

Chad Myers calls this Time to Login Screen, I like to think about this as: Time to Business Value, which is just a bit more ambitious.

To add to the burden, I am working with MonoRail after a long hiatus, and I forgot some things and missed other, so I need to ramp up on them again.