Ayende @ Rahien

Refunds available at head office

Rhino Mocks Future

Taking Rhino Mocks to the next level?

So I've improved the interface and added constraints and callbacks, this is nice, but I think I can do more. The first issue on the table is ripping some of the innards of the library and replacing them with something saner. I'd to hack quite heavily to get it to the point it's now. Five to six levels of indirections are not fun to go through when you need to understand what is wrong. I also don't agree with some design and implementation decisions that were made. I am also quite excited about the concepts that NMock2 has to offer.

Here is what I'm envisioning:

  • The explicit record / replay model is very good, and should stay as is.
    • Trying to move to implicit model would mean moving to string base expectations, which is unacceptable.
  • There needs to be an easier way to spesify constraints / expectations / callbacks and actions.
    • Contraints - the same thing as on the NMock world.
    • Expectation - what the exact method parameters are.
    • Callback - calling your code when a mocked method it called.
    • Actions - what to return or to throw when a mocked method is called.
  • NMock2 contraints are very easy to read, and should be copied.
  • Make the idea of all actions worked on last call explicit in the code. Currently this is implicit, and require deep understanding of the way Rhino Mock is implemented.
  • There need to be an easy way to spesify that I'm just expecting a call, and don't care about its arguments, as this is common scenario.

Taking all of this into account, here is how I would like to have tests in Rhino Mocks:

public interface IWalker
{
 void StartWalk();
 void WalkFaster();
 void EndWalk();
 void Rest(TimeSpan howLong);
 void Drink(int howManyLitters);
 int CalloriesBurned { get; }
 int WalkSpeed { get; set; }
}
[Test]
public void IdeadsForRhinoMocks()
{
 IMock mock = new Mock(typeof(IWalker));
 IWalker walker = mock.ForType(IWalker);
 
 walker.StartWalk();
 Set.Result(walker.WalkSpeed,5).Once();
 walker.WalkFaster();
 Set.Result(walker.WalkSpeed,7).Times(3);
 Throw.On(walker.Drink(0),new NotEnoughWaterException()).Arguments(Args.IgnoreAll);
 walker.Rest(new TimeSpan());
 LastCall.Arguments(Is.GreaterThan(new TimeSpan(600)));
 walker.WalkSpeed = 15;
 LastCall.Callback = new VoidDelegate(ThrowCantWalkThatFast);
 walker.EndWalk();
 mock.Replay(walker);
 //Or mock.ReplayAll() 

 ITrainer trainer = new Trainer(Behaviour.Nice);
 trainer.Walk(walker);
}

What do you think of the interface?

I also want to add strict method orderring vs. relaxed method ordering. Again, NMock2 show a particular elegant way to do that.

Mr. & Mrs. Smith

 

Great movie, I couldnt' stop laughing all the way. Highly recommended.

[Listening to: Lammas Night - Heather Alexander - Magic, Moondust & Melancholy(08:16)]
Tags:

Published at

Beta place annoys me

I don't know how many of you have run into the annoyances of Beta Place, this is the first time that I'm downloading a Microsoft beta from this site. All the previous betas were open ones, which didn't require registration.

Let's start with the list:

  • You must register (beyond Passport), I'm not certain why, since they already has my details in Passport, but that is common enough so I would need to comment on.
  • When you are finished registering, you have to wait 24 hours. Presumably for human to approve you, this is less convenient than it should be, but still acceptable.
  • In my case there was a glitch, and I had to register multiply times in order to get the required access.
  • When you finally get to the point where you can actually download the files, you realize that Firefox is not working :-(, I just got a bgValut.asp file which didn't really help. I tried Explorer, but it throws a generic VBScript error that isn't very helpful. On a hunch, I tried to run Explorer as administrator, and there I realized. You need install an ActiveX control in order to download the software. I don't know what plain http/https are not good enough, but some warning would've been nice. It was very frustrating to be so close to the software and not be able to get it.

That being said, I now has Monad install so I can play with it. :-)

CodeProject article

I put an article in CodeProject about Rhino Mocks, I edited the article in Word, and the strange formatting clashed horribly with CodeProject's formatting. Took a long time to fix. Now it's there, I'm working on a PDF format that will include some more infromation, should be out soon.

On other news: I really like what NMock2 can do; I'm going to rip the guts of Rhino Mocks anyway, so I'm going to implement that as well.

"IBM: It's Been Malfunctioning" -- Tech Support Slogan
"To be, or not to be, those are the parameters." -- Tech Support Slogan
"Michael Jordan makes more money from Nike annually than all of the Nike factory workers in Malaysia combined." -- Fact of lifes

[Listening to: Alone - Big Country - best of driving rock (4 of 6)(05:11)]

NMock2: Funny Tests

Go are read this file, it's part of NMock2's tests, and it's the first time that code made me laugh.

What can I say, I like Knock Knock jokes :-)

"To punish me for my contempt for authority, fate made me an authority myself." -- Albert Einstein
"Those who beat their swords into plowshares will plow for those who don't." -- Army Sergant
"Disc space, the final frontier!" -- Tech Support Slogan

Rhino Mocks & NMocks 2

I just read Roy's message about NMock2. Vaderpi talks about it in more details, it's look very nice.

Here is the original NMock test:

[Test]
public void ComputeTotal() {
  // Create the mock object for item1 and have it return a price of 100
  DynamicMock item1Mock = new DynamicMock(typeof(Item));
  item1Mock.Strict = true;
  item1Mock.ExpectAndReturn(\"Price\", 100);
  Item item1 = (Item) item1Mock.MockInstance;

  // Create the mock object for item2 and have it return a price of 50
  DynamicMock item2Mock = new DynamicMock(typeof(Item));
  item2Mock.Strict = true;
  item2Mock.ExpectAndReturn(\"Price\", 50);
  Item item2 = (Item) item2Mock.MockInstance;

  // Add the items to the cart
  ShoppingCart cart = new ShoppingCart();
  cart.Add(item1);
  cart.Add(item2);

  // Get the total and make sure it is 150 (100 + 50)
  int total = cart.ComputeTotal();
  Assert.AreEqual(150, total);

  // Verify that all the expects have been met
  item1Mock.Verify();
  item2Mock.Verify();
}

Here is the NMock2 version, it looks much clearer, if a bit long.

[Test]
public void ComputeTotal() {
  Mockery mock = new Mockery();
  // Create the mock object for item1 and have it return a price of 100
  Item item1 = (Item) mock.NewMock(typeof(Item));
  Expect.Once.On(item1).GetProperty(\"Price\").Will(Return.Value(100));

  // Create the mock object for item2 and have it return a price of 50
  Item item1 = (Item) mock.NewMock(typeof(Item));
  Expect.Once.On(item1).GetProperty(\"Price\").Will(Return.Value(50));

  // Add the items to the cart
  ShoppingCart cart = new ShoppingCart();
  cart.Add(item1);
  cart.Add(item2);

  // Get the total and make sure it is 150 (100 + 50)
  int total = cart.ComputeTotal();
  Assert.AreEqual(150, total);

  // Verify that all the expects have been met
  mock.VerifyAllExpectationsHaveBeenMet();
}

And here is Rhino Mocks version:

[Test]
public void ComputeTotal() { 
 //Create mock controls and mock objects
 MockControl control1 = MockControl.CreateControl(typeof(Item)); 
 MockControl control2 = MockControl.CreateControl(typeof(Item)); 
 Item item1 = (Item)control1.MockInstance, item2 = control2.MockInstance;
 
 //Setup return value and expected call 
 control1.ExpectAndReturn(item1.Price,50); 
 control2.ExpectAndReturn(item2.Price,100);
 
 //Prepare for replay 
 control1.Replay(); 
 control2.Replay();
 
 //Add items to cart 
 ShoppingCart cart = new ShoppingCart(); 
 cart.Add(item1); 
 cart.Add(item2);
 
 // Get total and verify that we got the correct result 
 int total = cart.ComputeTotal(); 
 Assert.AreEqual(150,total);
 
 //Verify that all expectations have been met 
 control1.Verify(); 
 control2.Verify();
}

All three version express the same intent. I already talked about why I don't like NMock very much. I didn't have a chance to use NMock2, so I can say if it has any shortcoming, but I* think that there might be a problem in expressing complex conditions.**

I'm going to write a code project article for Rhino.Mocks, so far I think that only 1 Frown person downloaded it.

* Am I spearding FUD? I'm not really objective, you know ;-)

** Rhino Mocks solution is to use callbacks and verify the method using Asserts.

Statistics

While creating the website I got interested in the logs for my blog, so I decided to take a look. It took me some time, and in the process I made some nice tools that would help me in the future. Some interesting facts, in the last four months I had ~38,000 page views.

Here are some of the interesting search terms that sent people to me, in the tradition of Eric Lippert, I added capitalizations, but nothing more. There were a bunch more that I couldn't print here, inclduing some that were very suprising. And I've seen the dark side of too many prisons to be easily surprised.

Rotten body parts:
Move along, please. I worked at a butcher once, didn't like it very much then, and I'm certain that I wouldn't like whatever it was this search was for.

Pictures of invisible braids:

This a truly philosophical question. It has been asked before, of course, but according to Return To The Future, such a thing would destroy the universe, so I would refrain from answering.

Hebrew curses+russian:
I know quite a few, but I tend to curse in russian, that way I don't feel so bad about it :-) It's a wonderful language for curses, they roll of the tongue with a most satisfiying omnious sound.

Norton takes too long startup:
Get rid of it, I did, and my life has been better :-)

Baby sheering coats:
Aren't there lows against baby-labor? Shearing is hard work. I suggest letting the baby grow a few years?

The story of how a monkey and a wolf were put tighter to make a money wolf:
Hm, that is an interesting, and profitable, cross-breeding. Perhaps I should switch proffessions?

Racing frogs cheats [and many other variations]:
Well, there is that trick with the ginger, but seriously, racing frogs? What happened to the worlds, next we would be herding cats.

Redder statues ghosts:
Nope, all the ghosts I know are white or blue. :-)

Males height can grow taller through swimming:
The funny facts you find out when you read the logs, imagine that.

Who could ignore a baby?
Certainly not me, I adore them.

Funny typing mistakes:
Hi! I don't make that many to get listed for that search. Do I?

Someone to help fixing a sentence:
You got to the wrong place, dude. I can help mangle them, though.

The complete idiots guide to spelling:
Do you think google is trying to tell me something.

Amature wives:
I would be quite worried of the proffesional ones, they tend to outlive you :-)

Having fun with command promt:
I certainly don't [look at the comments], beta place hates me.

WARNING:
Thanks for the info, consider me warned.

Nasty rhino logo:
I object, it's a nice rhino!

Free C# TreeListView:
Last time I checked, there weren't any good ones.

Hbm Xml Hui Editor:
I'm working on that, honest!

TortoiseSVN actively refuse:
Then send it to the principal's office.

Prison logo:
A pair of handcuffs and a some bars, pretty easy to draw.

Books on prison life:
Ugly, boring and very unpleasant. Nothing to write home about. If you are searching in case you get in, I have one suggestion. Don't!

Resume with Java:
Sorry, my resume contains only C# & C++.

Tags:

Published at

Website & Cuyahoga

For a long time I tried to get a CMS to run on my site. The problem was compounded by the fact that I don't have SQL Server at this host. The database I'm using is MySQL, and not many CMS support that.

I also didn't have time to nurish a CMS so it would work. So I made do with what was basically a static web page that referred to my blog.

Now I downloaded and deployed Cuyahoga 0.8, and it has been a blast, both to install and to work with. I can say that my biggest problem was that I had to create a template to match my site. Very easy and inituative to work with.

So now I've a proper web site, with place to put my projects and a little more organization in life :-) You can get it at http://www.ayende.com/

Enjoy,

I certainly will.

Tags:

Published at

The intricacies of NCover

Apperantly there are two project that goes by the name of NCover, they have the same purpose but very different implementations.

The first, which I've used and didn't much liked, uses code source instrumentation to check the code coverage of your code. I found it unreliable and quite messy to work with.

The seocnd, however, is much much better. It doesn't require code instrumentation, but rely on the profiler API to do its work. It gives a very details view of the code coverage in your code. However, it's not without its quircks, and I fought against it head on for the last couple of hours, so I thought to document some of the important thing here, for future refernce.

The first thing to notice is that the tool require that the CoverageLib.dll will be registered, this means that if you're moving it to a new computer using xcopy setup, you need to manually register the CoverageLib.dll.

The second thing is that it can only create coverage reports for debug assemblies with their pdb files.

It took me quite some time to discover what was wrong, as there was no error, just empty result files.

"Most hospitals make money by selling the umbilical cords cut from women who give birth. They are reused in vein transplant surgery." -- Fact of lifes
"Zero to bitch in 2.4 seconds" -- Bumper Sticker
"The toothbrush was invented in 1498." -- Fact of lifes

[Listening to: רוחות מלחמה-רמי קלינשטיין - - (04:22)]
Tags:

Published at

Warning, Rhino In The Wild

Well, I'm ready to release Rhino.Mocks, I was right to dog-food it before I release it, I added again the ExpectAndReturn & SetupResult methods, since they are just so much more useful and convenient than doing it on your own.

To be short, here is the source, and here is the binary. The source rpository is: svn svn://svn.berlios.de/nqa/Tools/Rhino.Mocks/

I also created a toturial for using it, which can be found here. If you find it useful or think of an improvement, please drop me a note. It's 5:41AM here, and somehow the night gone away without me noticing it again.

"Stack Error: Lost on a cluttered desk..." -- Tech Support Slogan
"The best accelerator available for a Mac is one that causes it to go at 9.8 m/s2" -- Tech Support Slogan
".Net Users: Due to the holiday, there will be no garbage collection on Monday." -- Tech Support Slogan

[Listening to: éìãä ùì ëøîì - àðåðéîéí - ôøçéí á÷ðä(03:26)]

Rhino.Mocks Goodness

What are you saying about setupping mock code this way?

mockMainPresenter.SetupResult(mainPresenter.CurrentProject,prj);
mockMainPresenter.SetupResult(mainPresenter.Repository,repository);

Clear, concise, and ReSharperable*

In short, I added some of the convenience methods I removed earlier because... well, they are so convenience :-)

What I added is the SetupResult() and ExpectAndRetrun() and their deriatives. I still don't think that ExpectAndThrow() should return, as you may want to use this with a void returning method, and then you'll get a compiler error.

* Did I just created a word?

"You don't have to know how the computer works, just how to work the computer." -- Tech Support Slogan

Tags:

Published at

Referral spam

I started to get some trackback spam, so far it's not bad only a couple of sites. I'm not sure how to handle trackback spam in dasBlog, though. I currently added them to the referral spammers list, but I don't believe that this handle trackbacks as well.

Is it a sign that I'm important enough now to get spam :-) I currently seem to get ~400 visitors a day, so I guess that is enough for problems to start.

"Now I shall go to sleep. Goodnight." -- Final words of Lord George Byron, writer, d. 1824

Tags:

Published at

Blog Reading: It never ends

I'm trying to catch up on my blogs reading list (which I managed to squeeze to less than 200), the problem that I neglected that for the last couple of days, and new content keep appearing, I just finished one category and move to the next, and then there are more posts there.

Good content, though.

[Listening to: Demonbane - The Last Herald-Mage: Vanyel - Shadow Stalker: Songs of Vanye(05:52)]
Tags:

Published at

Introductin Rhino.Mocks

 Okay, so I've been so deeply coding there that I didn't get time to go online and post anything, but now I've nearly finished it, I'm ready for a 0.9 release.

The To Do List:

  • Add a way to easily ignore a method (currently can only do so globally).
  • Dog food it like crazy, the tests pass, but I want more experiance using it first. I made some UI (interface speaking) that I'm not so sure of.
  • Go over all possible errors and make sure that they don't retain the old interface.

The good:

  • Constraints: I added NMock's like Constraints (currently just a subset). Work just like NMock, only you get strongly typed interfaces and refactoring support from all the tools.
  • Callbacks: I added a native [Read: Not a hack] way to get called when a mocked method is called.
    Detailed Error Messages: Very good error messages support. This is the work of EasyMocks.Net, actually. But I added some minor stuff as well.
  • .Net Interface: No longer burdened by its Java heritage, Rhino.Mocks has a shiny new dotNetty like interface.
  • No more fake constraints just to get NMock to decide which overload I wants. (See the second example, for the AddException() call)

The code:
Here is one of NQA's tests [one of the simplest ones] using NMock:

[Test]

public void SaveProjectAs_CanBeCanceled()

{

      mockProjectView.ExpectAndReturn("Title",prj.Name);

      mockProjectView.ExpectAndReturn("Ask",null,new IsTypeOf(typeof(string)),null);

      Assert.IsFalse(presenter.SaveProjectAs());                 

}

Here it is using Rhino.Mocks:

[Test]

public void SaveProjectAs_CanBeCanceled()

{

      getDummy = projectView.Title;

            mockProjectView.Returns = prj.Name;

      projectView.Ask("Project name:","Test Proejct")

            mockProjectView.Returns = null;

      Replay();

      Assert.IsFalse(presenter.SaveProjectAs());           

}

As you can see, the Rhino.Mocks one is longer, because we need to specify the returns seperatedly. But the advantage is in code that is both more explicit and clearer.

Here is one of the more complex tests in NQA, it verify that a thread properly handle its exceptions. This was very difficult test to write because I need some behaviour in the mocked class. The options were delegating constraits or write a mock by hand. The hack was faster. The test include that incredibly hackish DelegatingConstraintWithArgs as well, which is another red flag.

[Test]

public void ExceptionInQuery_DoesNotThrowButReportsException()

{

      DelegatingConstraintWithArgs executeInUI = new DelegatingConstraintWithArgs(

            new ExecuteInUIThreadDeleagate(ExecuteInUIThread),2,"");   

      DelegatingConstraintWithArgs executeCommand = new DelegatingConstraintWithArgs(

            new ExecuteCommand(executeCommandDelegate),1,"");                      

      mockMainPresenter.Expect("EnqueueCommand",executeCommand);

      mockIQueryView.Expect("ExecuteInUIThread",executeInUI,executeInUI);

      mockIQueryView.SetupResult("HqlQueryText","Bad HQL Query");

      mockIQueryView.SetupResult("Parameters",new Hashtable());

      mockIQueryView.Expect("StartWait",null,null,null);

      mockIQueryView.Expect("EndWait",new IsTypeOf(typeof(string)));

      mockIQueryView.Expect("AddException",new IsAnything());

      presenter.ExecuteQuery();

      executioner.Run();

      while(!executeInUI.DelegateCalled)

            Thread.Sleep(100);

}

I'm refactorin to Rhino.Mocks as I'm writing this... please hold:

[Test]

public void ExceptionInQuery_DoesNotThrowButReportsException()

{

      executeInUI_DelegateCalled = false;

      mainPresenter.EnqueueCommand(null);

            mockMainPresenter.Callback = new ExecuteCommand(executeCommandDelegate);

      queryView.ExecuteInUIThread(null,null);

            mockIQueryView.Callback = new ExecuteInUIThreadDeleagate(ExecuteInUIThread);

      getDummy = queryView.HqlQueryText;

            mockIQueryView.AlwaysReturn = "Bad HQL Query";

      getDummy = queryView.Parameters;

            mockIQueryView.AlwaysReturn = new Hashtable();

      queryView.StartWait("Executing query",100,1000);

      queryView.EndWait("An exception occured executing query");

      queryView.AddException(null);

            mockIQueryView.Constraints(new IsTypeOf(typeof (QueryException)));

      Replay();

      presenter.ExecuteQuery();

      executioner.Run();

      while(!executeInUI_DelegateCalled)

            Thread.Sleep(100);

}

Both tests are without their setup/teardown & supporting methods, but they should provide a good indication to the way that writing tests in both libraries encourage. In the Rhino.Mocks test I used all three approachs for verifying. Straight equility, when I'm simply calling the method and passing the parameters that should be passed during the test. Constraints validation. And custom validation & actions via callbacks.

This makes Rhino.Mocks a hybrid, with the good of both worlds. I'll finish porting NQA to Rhino.Mocks and then I'll post some more about it, a detailed fact sheet (NMock's documentation is the best, accurate, to the point, and all of it in one page) and, of course, the code.

Tags:

Published at

Even more Norton Anti Virus crap

After removing Norton Anti Virus from my main computer, it somehow detected that and started bugging me on the laptob, every time I open an office application it informs me that it can't repair itself and I need to uninstall & install again.

The moment I get to a place with network connection where they don't charge by the kilobyte, you can guess who is going away...

Tags:

Published at

Programmer's tricks are nasty and cruel

[As a note, I'd this post open since this morning, and contiously added more to it as time went by.]

I hate tricks. If you recall, I wondered about all those not implemented GetHashCode(), they were because EasyMock.Net override the Equals method in a class that represent method's arguments, and then put it in a dictionary. Part of the logic of verifying and validating that the mock passed is to query the dictionary for the existance of the arguments. I'm not explaining it very well, basically, they were doing things like this:

ResultList list = (ResultList) resultListMap[expected];
if (list.HasValidCallCount && !expected.Equals(actual))

What this does is to scan through the dictionary, comaring each argument set to the expected one. Further more, this is possible:

Assert.IsNull(resultListMap[resultLimpMap.Keys[0]);

This is just wrong, and that was where it all started to break. I wanted to add constraints to the library, and for the life of me I couldn't fiigure out how it validated things. This is a properly designed application, full of patterns and well defined interfaces. This translate to hard to read if you don't have a clue about the code. (I only heard about it two days ago). Some of the method calls took 8 levels to reach the level they were doing something, all along adding context. It wasn't fun to discover how it worked. It is fun to work with it now that I know how it's working, though.

So I write a test to the functionality that I want, make my change, and run all the tests again. All the tests except mine passed. Finding out about this wasn't fun. This is a very nasty trick.

Nevertheless, the thought behind this library is amazing. The nasty piece of code above is limited to a single class. So it's pretty easy to change, once I figured out what was wrong. I currently managed (after three failed attempts [because I didn't understand fully what was going on] to add constraints to the library. Ironically, I'm currently using NMock's constraints, since building both the constraints and the constraint infrastructure was too much.

I just finished re-implementing NMock's constraints. Very easy to do. Demonstrate that a lot of tiny pieces can have incredible value, iff* you know what their environment is.

I just implmented yet another great feature, Callbacks. This means that you can register for a method, and you'll get called with the method arguments. This allows for very powerful validation** and behaviour during tests.

I'm going to dog food it tomorrow, by converting NQA to use it, and then I'll release it. I think that it turned out to be a pretty good tool in the end.

* This is not a typo

** And much abuse, incidently :-)

Tags:

Published at

NQA on NUnit

I've moved to NUnit from MbUnit, this has been going on in my head for quite some time, there is a wealth of tool support for NUnit, and very little for MbUnit. Mainly, I was moved by easy CC.Net integration (yes, I know that MbUnit has that as well, but not built in and not as easily), Nester, and other tools which all require NUnit. Beyond that, MbUnit ceased to give added value over NUnit some time ago, so in the end, I had to ask myself more Why? than Why Not?

GoodBye to EasyMock.Net?

I'm making extensive interface changes to EasyMock.Net, I think that at this point it's not really the port from the original EasyMocks. I think I'll call it Rhino.Mocks.

The reason? Look at the logo, I like Rhinos.

EasyMock.Net: An Ah-HA moment, and more ReSharper glory

Just had one looking at the tests*; one minute I couldn't get what they were trying to do, and the second I got it and it was like: "This is so smart!"

Me and ReSharper and going through the code with an pickaxe and venegence in our eyes. I'm devoted user of ReSharper for a long time, and I can't believe how easy it is to do refactorying. It's like having an army of little coders that runs and do what I want, mostly without concious thought. This tool is smart. I'm making countless changes to the code, the code compiles, the tests pass, and I don't have to do anything more than will it.

One strange thing, I keep bumping into code like this:

public override int GetHashCode()

{

      throw new NotImplementedException("GetHashCode() is not implemented");

}

Anyone can think of a reason to do that?

* This is the first time I'd to read other people's tests, I'm starting to get why XP is so keen of them.

Tags:

Published at

EasyMock.Net: dotNetified

As I said, EasyMock.Net looks pretty impressive, but it still has a very strong Java background, meaning javadoc comments, all caps enumerations, etc. First things first, I needed to .Net it. I am constantly surprised by how wrong a feeling a different coding style can give me.

  • Renamed ArgumentsMatcher => IArgumentsMatcher
  • Converted Javadoc comments to C#'s XML Comments - highly tedious process.
  • Replaced Boolean => bool
  • Replaced String => string
  • Replaced Object => object
  • Removed /*sealed*/ comment
  • Removed useless cataches
  • Replaced Throwable with Exception
  • Replaced ALL_CAPS with CamelCasing for variables & enumerations
  • Replaced MockControl's ONE with Once, ONE_OR_MORE with MoreThanOnce and ZERO_OR_MORE with Any

This is enough for now to give it far more dotNetty feeling than an imported Java library. Things that I want to do with it:

  • Adding an easy way to add constraints.
  • Allow to chain expectation.

More will follow, probably :-)

Interesting tidbit, a developer that asked whatever the project was still alive got the project assigned to him. :-)

Tags:

Published at

Interaction Tests

The Shade Tree Developer has a post about TDD Design Starter Kit - State vs. Interaction Testing. I found it interesting because I recently had to use a lot of interaction testing.

I want to test the UI back end, and since I can't get GUI testing to work I'm using the MVP*to seperate presentation and logic. This results in code that looks like this (Please ignore the absimal error message, it's temporary**):

public bool SaveQueryAs()

{

      string name = view.Title;

      string newName = view.Ask("Rename query to:", name);

      if (newName != null)

      {

            Query oldQuery = mainPresenter.CurrentProject.GetQueryWithName(newName);

            if (oldQuery != null)

            {

                  if(view.AskYesNo("Query exist, overwrite?", "Overwrite query?"))

                      mainPresenter.CurrentProject.RemoveQuery(oldQuery);

                  else

                        return false;

            }

            if(Query.OwnerProject==null)

                  mainPresenter.CurrentProject.AddQuery(Query);

            Query.Name = newName;

            view.Title = newName;

            mainPresenter.Repository.SaveQuery(Query);

            view.HasChanges = false;

            return true;

      }

      return false;

}

The UI is composed of forms that implement various IXXXVIew interface (IProjectView, IQueryView, etc). State base testing is nearly useless in this case. The tests I've for this method currently are:

  • Save As can be canceled.
  • Save As rename the query and save it.
  • Save As with conflicting name can be canceled.
  • Save As with conflicting name & user approval removes the old query, rename the query and save it.

In order to test each of those, I'm mocking the view (hard to test it) & the repository (avoid touching the database). The problem I've with those tests is that they feel too... intimate with the object. Then again, I'm not testing the results of a calculation, I'm checking the results of interaction with the user, so there is no easy way to do that using state based testing.

One problem that I'd with this is that refactoring the code cause the tests to break, because I'm using NMock and the refactoring doesn't touch the method names in strings (I understand that on the Java side they are sophisticated enough to do that safely, and Resharper 2.0 should've this capability as well). I'm testing EasyMock.Net right now, it has some Java yuckiness strapped on, but it seems to be a much better solution for refactoring and readability of code than NMock. Unfortantely, it's compiled against an NUnit version from 8 months ago. I'll report more when I done with it. I really liked the way it works.

* Model View Presenter, not related to Microsoft

** There is a saying in the IDF, "The temporary is here to stay, the permanent things go away"

Source Code Metrics

I just read this post by Sahil, and it caused me to get SourceMonitor, which is an application to calculate all sort of interesting information about your code. The amount of information that this tool offers is simply amazing. The one thing that I regret is that there doesn't seem to be a way to integrate this into the build process and get an XML file to do work with. You can get it to work in your build process quite easily (they have an Ant script that I'm currently coverting to NAnt) and it should be useful for all sort of things beyond mere reporting. For instance, if I get beyond some complexity thersfold, the build would fail.

I'll post NQA's results as soon as I finish integrating this into the build.

[Listening to: Showdown - Electric Light Orchestra - best of driving rock (5 of 6)(04:12)]
Tags:

Published at

Vs.Net & Resharer tidbits

I had to re-charge my mouse, so I tried to use VS.Net without mouse at all, I opened VS.Net, and then moved to my current project, pressing the Return key did nothing, but space worked, strange, and unlike the WebUI metaphor.

They I got one of Resharper's startup help screens, and noticed that they had SourceGrid2 as one of their options. SourceGrid2, if you are unaware, it an OSS (BSD license) project to create an infinently flexible gird. I've played with it before, and it's very good although quite complex.

Tags:

Published at

Even More Anti Virus

Well, I rebooted (23 days uptime down the drain), but what is interesting, that after the reboot, I did a Live Update, and it requested reboot again. Where is that uninstall again? No it's working, and I don't have Norton System Reboot on my computer anymore. I still have to do another reboot to remove all the fluff. Yuck!

I did manage to install AVG, I think that Norton did something to prevent the install. It's running the full system scan right now, and I don't feel it at all. I had to uninstall Norton previously because it slowed down the computer so much. I have a good feeling about this.

Tags:

Published at