Oren Eini

CEO of RavenDB

a NoSQL Open Source Document Database

Get in touch with me:

oren@ravendb.net +972 52-548-6969

Posts: 7,567
|
Comments: 51,185
Privacy Policy · Terms
filter by tags archive

TDD Goodness

time to read 1 min | 184 words

I just had a complete surprise writing a test for Rhino Mocks. I'm doing that completely Test First, and I wrote a test, expecting it to fail. But it passed. Apperantly I'm already covering this case. :-)

This is so nice.

[Update: (five minutes later) Now it begins to be scary. I just wrote another test, for a part that I knew should be hard to get working. And it passed as well. The code handles it just fine, even though I thought I would need extensive changes to get it to work. I'm talking about ~1,300 LOC, and it still manages to surpirse the hell out of me.]

"E Pluribus UNIX." -- Tech Support Slogan
"If I had my life to live over again, I'd make the same mistakes, only sooner." -- tallulah bankhead
"The world is coming to an end... SAVE YOUR BUFFERS!!" -- Tech Support Slogan

[Listening to: Michal Amdursky - Pillow Talk - - (03:53)]

The REPL in .NET

time to read 2 min | 279 words

A post in Project Aardvark biog by Benjamin Pollack contains some very disturbing ideas:

Thirdly, you can’t easily write and test just a small amount of code. In most languages, your only option if you want to do this is to write a test suite for your class protocol, which takes a lot of time during development and probably isn’t necessary for a lot of smaller stuff.

Didn't you guys heard about Test Driven Development? You can get it in most languages now aday. In .Net, the common framework is NUnit (but I like MbUnit as well). In C++, you have CppUnitLite. The issues he is describing sounds like normal legacy code and can be solved using the techniques listed in Working Effectively With Legacy Code.

REPL is nice, but it is good for playing with the langauge; to see what will happen if you do XYZ, not to verify that XYZ indeed happens. I know that Joel's Test doesn't include Unit Testing, but still...

This is sad. Benjamin, get yourself a copy of the following books and read them, you'll likely learn a lot.

Product image for ASIN: 0735619484 Test-Driven Development in Microsoft .NET

Product image for ASIN: 0596007396 NUnit Pocket Reference

time to read 2 min | 332 words

I'm going over NQA's test coverage right now. I added tests to some areas that desperately needed tests, and several code paths that weren't tested. The best parts were that I found pieces of dead code that I could just remove. As usual, ReSharper is invaluable in finding those parts.

I'm partly dog-fooding Rhino Mocks, and I got some interesting ideas for improvement, and partly to actually get a better code coverage on NQA :-) [I just thought that I've found a bug in NQA, but it was in my tests.]

I didn't have much chance to touch certain parts of the code, specifically, the SchemaEditing parts, and going over the tests is a great way to reacquaint myself with what is going on there. 

On the other hand, it's kind of depressing, I look over the list, and there is so much red there... :-( I'm currently reading Working Effectively With Legacy Code right now, and the definition there is "Legacy Code is code without tests."  On the third hand*, the book offer good advice about how to handle that. I wish I would've read it five months ago, I would've made a lot of different choices in how to bring NQA to the Fun-To-Work-With world.

I've finished reading  Extreme Programming Explained : Embrace Change (2nd Edition), and I'm not sure what to think. On one hand, it's the first book that actually made me put it down and reach for the code. On the other hand, it seems that it's not quite an introductory text but more of a guide. It wasn't what I expected, that is certain. I think I'll need to re-read that (which I don't usually do for tech books) to really grok what Kent is trying to say.

* It's pretty handy when juggling, too. :-)

time to read 2 min | 395 words

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.

time to read 2 min | 311 words

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. :-)

time to read 2 min | 276 words

I've one test class that takes over a minute to execute(!), that is unacceptable. Taking a look inside, I can see why this is so, it construct the database and creates an AppDomain on each and every test. Moving those to the TestFixtureSetup made it run in 1.6 seconds, which I consider far better.

The second offender took only 22 seconds to run, also for the same reason, moving to TestFixtureSetup can it down to 1.5, which is much better. The other main offender was 10 seconds (down to 0.67).

It took me 30 minutes, and I cut the time to run my test suite from over 140 seconds to 27 seconds, but that is still not enough.

One class is testing the AppDomain load/unload, so there isn't much that can be done about it, but I still managed to move it from 10 seconds to 5.

The next thing to tackle was 14.5 seconds spent on UI testing. I've commented before, databases and networking may be slow, but until you look at the timing for UI tests, you won't believe how slow the UI is.

Considerring my previous diffculities with testing the UI, I removed those tests all together, and removed the reference to MbUnitForms.

Total time to run the tests before "optimization"*: 140+ Secodns.
Total time to run the test after "optimization"*: 11.45 seconds.

Now I no longer have to look for something else to do while I'm running the tests. :-)

time to read 18 min | 3593 words

Anyone can suggest a pattern to do that? I'm currently trying to test some of my multi threaded code, and I get into a whole lot of trouble.

The problem is that I'm trying to test that things happen in two threads at the same time, and I'm not sure I'm doing it properly. Per Udi's suggestion I changed my code to use notifications, rather than busy waiting.

Because of the need to syncronized between the threads, I created the following method:

public void ExecuteInUIThread(Delegate d, params object[] parameters)
{
  if(this.InvokeRequired)
     Invoke(d,parameters);
  else
     d.DynamicInvoke(parameters); 
}

The problem is how to test that the method called from the class I'm testing is the right one, I'm not so sure about how to do this properly. But before I get to the solution, here is the problem:

I've a class which is called from the UI thread to do work, it spun off a thread which does it works, and when done, it call the ExecuteInUIThread method with a delegate to an OnSuccess or OnFailure method. My problem is with the tests, how do I make sure that I get the correct response from the class. Take into account that I'm mocking the class which contains the ExecuteInUIThread method, and that is a complex issue.

I solved it this way, using a custom constraint in the mock object, which allows me to run my own test method when the mock is called, here is what I've, it's an extention of the idea I'd with DelegatingConstraint:

public class DelegatingConstraintWithArgs : BaseConstraint

      {

            private readonly string message;

            private readonly int numberOfParams;

            private Delegate d;

            private int currentParam = 0;

            private object[] args;

            private bool delegateCalled = false;

 

            public DelegatingConstraintWithArgs(Delegate d, int numberOfParams, string message)

            {

                  this.message = message;

                  this.d = d;

                  this.numberOfParams = numberOfParams;

                  this.args = new object[numberOfParams];

            }

 

 

            public override bool Eval(object val)

            {

                  args[currentParam] = val;

                  currentParam += 1;

                  if (currentParam == numberOfParams)

                  {

                      bool ret= (bool) d.DynamicInvoke(args);

                      delegateCalled = true;

                      return ret;

                  }

                  return true;

            }

 

            public override string Message

            {

                  get { return message; }

            }

 

            public bool DelegateCalled

            {

                  get { return delegateCalled; }

            }

}    

This class will gather the paramters of the method, and when it will reach the final number, will execute the delegate on them. This allows me to invoke the delegate that I get from the class under test*. I can execute it and then observe the effects.

On a more general level, this allows you to execute your own code from the mocked object, without writing much code. It's nice, but very much open to abuse, and more over, I'm not so sure that I'm not abusing it myself right now.

For instance, here is my current test, I setup quite a bit of expectations that it needs, and then run the tests, waiting until after the method is called. Verify()ing the mock is done on the TearDown() method.

[Test]

public void ExecuteQuery_NoParameters()

{

      ExpectNoError();

      DelegatingConstraintWithArgs cs = new DelegatingConstraintWithArgs(new ExecuteInUIThreadDeleagate(ExecuteInUIThread),

            2,"-not-relevant-");

      mockIQueryView.SetupResult("HqlQueryText",nonParametrized);

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

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

      mockIQueryView.Expect("DisplayObjectGraph",

            objectGraphConstraint);

      mockIQueryView.Expect("DisplayDataSet",

            new And(new IsTypeOf(typeof(DataSet)),dataSetConstraint));

      mockIQueryView.Expect("ShowObjectGraph");

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

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

      context.ExecuteQuery();

      while(!cs.DelegateCalled)

            Thread.Sleep(100);

}

* As a side note, I've here two or three layers of delegates, spooky.

time to read 2 min | 223 words

Well, apperantly my last post about agile UI wasn't breaking any new ground, here are some pointers regarding it:

Model View Presenter -  Matt Berther, Here is a good description, from the comments of the post

The difference between MVP and class MVC is that in MVC the Controller changes the Model or the View and the View gets data from the Model. The model also updates the view when data changes.

Using MVP, the View only communicates with the Presenter. The presenter then communicates with both the View and the Model.

Posted by Matt Berther at January 14, 2005

Model View Presenter - Martin Fowler

More on Implementing an Interface in the UI, or the 7-layer system - Chris McKenzie

Agile UI

time to read 5 min | 885 words

Well, I'm been talking for quite a while about the problems you get when you get into when you're trying to build User Interface using Test Driven methodology. The main problem seems to be that in order to do TDD properly, you need to test things which are inherently difficult to test.

Add that to the fact that in .Net, most controls duplicate the displayed data, which means that it's easy to just start using the UI as the backing store for you data and you get a situation that it hard for testing and hard for doing agile work.

Right now I'm doing UI work in the following way:

  • Build the visible UI as simply as possible - this usually means using the form designer.
  • Create an inner class named Context which manage all the logic for the form. As a side affect, this class hold no state, which make it good for threading, but I'm not using this yet.
  • Wrap any data that the Context need with a property and make sure that it's accessed in a non UI-bound way.
    For example, if the form display a TextBox which should contain the user's name, the form expose a property:

    string Username
    {
     
    get { return usernameTextBox.Text; }
     
    set { usernameTextBox.Text = value; }
    }
  • Generate an interface (I just love ReSharper) for the required functionality from the UI.
  • Test the Context class against the interface.

This way allows you to still use the UI Designers, which can save quite a bit off work, and still maintain indefence in the logic from the UI itself. Later, I could move the context class to a Controller, but currently I don't feel the need.

What I do find is that code that works for Unit Testing sometimes produce code that is easy to test, but not to use. This is mainly because I'm not thinking through the tests, and I end up with code that is hard to work with. The advantage is that it's usually minor changes, and can be safely done with the tests existing. I made some big modifications (to the architecture of the application) and managed to carry them safely and easily with the tests that I've. I also began to fix problems by first writing a failing test, I caught myself this way several times already, and I know that what I would've done without tests would have only made it harder to find the error.

One of the drawbacks of this appraoch, however, is that I'm no longer using Test First approach. I first do a rough model, and code some basic functionality, and then test the logic behind it. Currently, I'm in discovery mode, meaning that I look at the UI, see what can be done, and then I do it. But when I'll move to more familiar area, I don't see why I can't do it in Test First way.

One thing I'm not sure of is how to store the data in the UI objects themselves, it does not sit well with me that I store it all in the controls. But considering that I usually work with something like this:

public interface IUserView 
{
 string Username { get; set; }
 SecureString Password { get; set; }
 string Email { get; set; } 

I don't see much Evil in doing it this way.

Any ideas?

NMock annoyances

time to read 1 min | 122 words

After praising it, I can't help but point some of the annoying parts.

The one thing that annoys me in NMock is setting expectation for a method call that has arguments. The problem is that there is no easy way to make NMock aware of method overloading, so it can't distinguish between MethodSample(string s) and MethodSample(int i).

Currently I work around it by using mockObj.Expect("MethodSample",new IsTypeOf(typeof(string))), but that just looks ugly, and I don't think that it would solve the problem if I would run into a real overloading scenario. Currently I've not solution for that, anyone has ideas?

[Listening to: רמי קליינשטיין - ריטה - צל הירח - - (04:26)]

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. Production Postmortem (52):
    07 Apr 2025 - The race condition in the interlock
  2. RavenDB (13):
    02 Apr 2025 - .NET Aspire integration
  3. RavenDB 7.1 (6):
    18 Mar 2025 - One IO Ring to rule them all
  4. RavenDB 7.0 Released (4):
    07 Mar 2025 - Moving to NLog
  5. Challenge (77):
    03 Feb 2025 - Giving file system developer ulcer
View all series

RECENT COMMENTS

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats
}