|
 Tuesday, April 01, 2008

NUnit 2.4.7 and the RowTest Attribute with Example

This last Sunday NUnit 2.4.7 was released. As usual, great bug fixes were implemented by the team for this release, but I think the key thing to note about this release is that this is the first release of NUnit to include an externally developed Add-In [Charlie Poole, altdotnet mailing list - 20080331].

The RowTest Add-In

NUnit now includes the RowTest extension, written by Andreas Schlapsi, in it's extension assemblies. This extension allows you to write test methods that take arguments and to provide multiple sets of argument values using the RowAttribute. To use RowTest, your test must reference the nunit.framework.extensions assembly. [NUnit 2.4.7 Release Notes]

This type of functionality is not something new to the community by any means. MBUnit developed this technology AGES ago- and honestly I think this one feature is the sole reason MANY Developers use MBUnit.

Ok, So what is the RowTest?

The RowTest Attribute allows you to specify different sets of data as declarative statements at the top of your unit test.

Example: Lets say we had to write 3 tests for 3 different sets of data. Here's a matrix of what we might need to test:

Specification Parameter 1 Parameter 2 Expected Result
Test Should Fail When Values are Null null null InvalidOperationException
Test Should Pass with two values of 5 5 5 7.07...<remainder omitted>
Test Should Pass With two ZEROS 0 0 0

In a previous release of NUnit we would have to write three unit tests for this because we can only assert one value at a time. Over time this causes duplication of code and you'll find that you have tons of test that nearly do the same thing, only with different values.

Enter The RowTestAttribute

With the RowTestAttribute (located in the NUnit.Framework.Extensions.dll) you can test rows of data with only one unit test. NUnit will run the unit test each time for each specified row of data.

Example (actual code files are available at the bottom of this post):

image

Which Tests this code:

image

Breaking It Down...

The Unit Tests in the first screen shot show two unit tests.

  1. The first one utilizes the RowTestAttribute
  2. The second one is how we normally test using NUnit.

Also note how we're using the new(er) Constraint Model for Unit testing. The unit test in the first set allow me to test via a "per row" basis. Utilizing the "RowTestAttribute" I can assign a set of data to the row and run that rows data via the values passed in. I can also expect exceptions, provide descriptions and messages - just like you would normally do in a classic NUnit test.

The second test is a basic example of what a normal Unit Test would look like. If we DID NOT use the RowTestAttribute we would have to write four unit tests to obtain the same functionality.

Setting It Up

The only thing you'll need to do to utilize the RowTestAttribute is to reference the nunit.framework.extensions.dll as well as the nunit.framework.dll. See below:

image

 

My Only Complaint

The only real complaint that I that I have right now is that ReSharper does pick up the "RowTest" attribute for unit tests, therefore it does not run the unit test. See the screen shot below:

image

This isn't a NUnit thing, its a ReSharper thing. If anyone knows how to get ReSharper to "see" RowTest as a valid Test, please let me know. Because the only way I can get this to work is to run it through the NUnit GUI or command line. (No I don't have TestDriven.NET installed either - but I'm assuming that TDD.NET would see this as a "valid" test).

 

Download Files (you will need the NUnit 2.4.7 Binaries to get this to run)

FooTheory.NUnit247.Example.zip 

Note: This is a VS2008 project. If you're running VS2005, just copy the .cs files as they are still valid 2005 format files and put them into a new VS2005 project and you'll be good to go. :)

#    Comments [3] |
 Monday, March 31, 2008

PhotoShop Express vs. Paint.NET

Almost daily, I use some sort of digital editing program. Over the years my top 5 tools for digital editing have been Paint.NET and Photoshop. I use both programs daily for editing screen shots, creating educational material/training manuals, and blog posts. I love Paint.NET simply for the fact that its VERY quick to load and performs easy tasks quite quickly. On my machine Paint.NET is up and running in under 5 seconds. Paint.NET helped get the easy tasks done, but when I wanted to perform true graphics manipulation and do some hardcore stuff, I'd fire up Photoshop. The one thing that always crossed my mind was why Adobe did not offer a "Photoshop Lite" type of program. Paint.NET has always been my "Photoshop Lite" since it was released. But, I still wondered why Adobe was missing out on this market.

Well, the other day Adobe released Photoshop Express. With my previous pondering finally answered, I HAD TO check out this product from Adobe. Could this be the "Photoshop Lite" I was hoping for?

My First False Assumption

My first initial impression upon reading the product SKU name "Photoshop Express" was that it was going to be a slimmed down version of Photoshop similar to Paint.NET that was installable. Having worked with Visual Studio for a very long time, I've become adjusted to recommending the "Express" SKU's to developers interested in .NET development. I'd recommend the Visual Studio Express SKU because it allowed them to get the feel for a good IDE (slimmed down on features of course) but they still got to use a lot of built in functionality, and it was FREE. That was the nice thing (note: if you're a student you can utilize the Dreamspark campaign to get a free version of Visual Studio Pro, and other products).

Was this the slimmed down version? No... not at all. Not only was this version not slimmed down, it wasn't even installable - its a pure browser based solution. I was thinking that maybe it was a "Click Once" app, nope. Not even close. This is purely a browser based solution. Ok, that's not too bad, then I started to use it...

My Second False Assumption

I believe a company of Adobe's caliber would be able to create a compelling graphics app that would be very responsive and effective - regardless of the platform (install or web). Anyone who has worked with any graphics program knows that they are memory hogs. Literally, they eat memory for breakfast, brunch, lunch and dinner (and some snacks between). They need to utilize a vast memory base to keep the program responsive - I like to say - if its a' swappin' it's a' doggin'. I had assumed that this program would be snappy like its big brother Photoshop. Nope. Not at all.

Since Photoshop Express is a web based hosted solution the images have to be uploaded to the server. The problem lies in the last four words of that sentence. Uploaded to the server. I don't know about you, but there is nothing snappy about loading up a 2MB file to a web site. Applying the filters are rudimentary, adjusting contrast, color balance and other tasks leave your image looking like you took a trip back to hippyville with too many pink elephants.

Conclusion

I had assumed I might be able to replace Paint.NET with Photoshop Express upon its initial release. Unfortunately Photoshop Express is insanely slow and the graphic manipulation tools that I need to accomplish my tasks are not what I need them to be. The lack of options are kind of a bummer and the responsiveness of the app is less than lackluster. But I'll say this... its a good attempt. Maybe version 2.x will be better.

How could Adobe get me to use the app? They could make it a Click-Once app. Make it a local installation. Follow the Visual Studio Express SKU model. Look at Paint.NET, It's worked great for them, why wouldn't it work for Adobe? I know they have a ginormous Apple following so they'd have to use a installation procedure that would work with MAC's as well as Windows. Possibly supporting two different models of the software is just too much for them at this point to foot the bill for a Free product and support. But, if they did go down the route of an installable Express type of app, I'd be all over it.

For the meantime I'll be sticking with Paint.NET. It's installable. Its a subset of Photoshop Features, and the real key is... ITS FAST. Any tool that I use MUST BE FAST. If its not, its gone.

 

Click thumbs for larger image

Screenshot of Paint.NET Screenshot of Photoshop Express
image image
#    Comments [2] |
 Sunday, March 30, 2008

I Can't Read Your Screen, Mr. Presenter

We've all been there, at the code camp/user group meeting/conference/etc where we CANNOT read the screen. Even though your code is projected onto a gigantic screen I cannot see you 10pt Courier Font, Mr Presenter, from 50 feet away in the back row. The audience faces contort and become scrunched up to the point of looking like the human version of a pug.

This is one of my biggest pet peeves during a presentation - the presenter may know the content like no other, but they don't have the skills to present their content properly. What's even more amazing is that that 9/10 presenters (in my personal experience) do not attempt to adjust the font on their screen to increase content readability. Aren't you trying to teach me something Mr. Presenter? I can't learn what I can't read. :\ As said before by many others, if you, as the presenter say "You know, you probably can't see this..." - you're right, and you're wasting my time. You've got a gazillion pixels on the screen, make them work for you. :P

What if the presenter bumps up the font to 18pt? That's all well and fine, and I can see the content, but I still have NO IDEA what the heck that 8pt menu font says, nor what menu you clicked on to get to that magical wizard that writes N-Layer architecture systems with a click of a button (sorry, got side tracked).

Gimme Da' Big Font's and ZoomIt Buddy!

Here's what I do when I'm giving a presentation...

  1. Use ZoomIt. I'm utterly baffled by how many presenters do not know about this tool. It's been around for quite awhile too! This tool allows you to zoom into a certain part of your screen with variable magnification. Once zoomed in, you can draw on your screen with multiple colors, write text on the screen and even change the color. You can also draw shapes as well (ellipse, rect, straight line). To view the options, double click the image ZoomIt  icon (shown here to the left).
    • How does it work? Simple, fire up the app. It will run in the background. When you hit the CTRL + 1 key combo, the screen is now magnified. Use your mouse to browse the the area where you want to display additional info.
    • I've created a simple screen cast, which is below. Click to watch. (there is no sound in this, it's just here to demonstrate what can be done).
    • ZoomItDemoThumbnail
  2. Create an Account that has Big Fonts. I prefer to set up an additional account on my machine that has all of my tools set up. I mean, everything has big fonts. From the command line to Visual Studio, to Notepad++. These are nice, big ol' fatty fonts. Trust me, its not pretty to look at, but for presentations it does well. You can adjust the font size of your machine by setting the font size in the control panel as seen below:
    • Note: This will REQUIRE a restart.
    • image
    • image
    • image

 

 

Next time you're presenting, don't forget the reason you're there - to present FOR AN AUDIENCE. Be kind to their eyes! Let them see what you're doing. Trust me, you'll get higher scores on your review sheets.

#    Comments [0] |
 Friday, March 28, 2008

Implicitly Typed Locals - R# V4

Recently Ilya Ryzhenkov posted a thread on the ReSharper blog. The article was about how R# 4.0 gives you a suggestion to use implicitly typed locals.

I've been running R# 4.0 nightly builds for a few weeks now and I've noticed these little buggers popping up all over the place.

Here's what it looks like:

image

 

Usually, I nearly agree with most of everything the R# team posts and even though sometimes I may disagree with something, I'll find the edge case where it does apply, so we're at a 99% agreement rate with them! Hell, you can't lie about it, R# seriously improves your productivity and it only keeps getting better.

Unfortunately, this is the one time I'm going to fully disagree with this post and actually the suggestion in R# - which is why I have disabled it. You can disable it  by going to the R# options:

image 

 

Why I Disagree

The post stated that "It induces better naming for local variables". I don't know about that. I can still call an apple an orange and call a orange a banana I want. Nothing forces me to do anything. The only thing I know at that point is that it's still an anonymous type. A name is that, just a name. Nothing forces developer x to write a good variable name. I still see Junior developers using wrong variable names. The only thing that's going to help here is a good code review process.

The post then goes into to say that it "It induces a better API". Again, I don't agree. How can this induce a better API? I feel that letting the compiler choose which types it is returning has its validity in certain cases, but not inside of your entire system. It brings back the horror days of VB's "Variant" (and yes, I'm aware that var is not Variant and I know the differences - but have you seen an old system where EVERYTHING was a variant? Oh my jeebus, save me now). Just because I'm letting the compiler do the work doesn't mean that I should have "good variable names" to help me distinguish what I'm working with.

This the one that sent me over the top... "It removes code noise". *insert sound of game show buzzer* Yeah... um... I'd have to say that's complete non-sense (in my opinion). Over use of the var keyword is going to add code noise and is definitely a smell to me. If I open up a class and see everything as "var" type, I'm going to cringe. The readability of this code has diminished to a point where its now costing me more money to maintain and read the code than it is if I were to use a strongly typed variables when I could. Even the MSDN states:

Overuse of var can make source code less readable for others. It is recommended to use var only when it is necessary, that is, when the variable will be used to store an anonymous type or a collection of anonymous types. [Source]

The last one is almost not worth putting into the post... "it doesn't require a using directive". Wait a minute... I bought ReSharper so I could be more productive... hitting ALT + ENTER to add the directive isn't a bad thing. Who cares if another directive is up there, that's what its used for, to tell the compiler what blocks of code look into during compilation.

Conclusion

This is not a bash on the ReSharper guys, not at all, but an explanation of why I disagree completely with this post. Heck, I agree with most everything on that blog (most of the time) and I'll never speak up about it. I'm a huge ReSharper fan and I will continue to use it and proclaim its greatness, but while reading this post I noticed a smell immediately. While using var has its uses, I think it can be abused.

The saying goes... "When all you have is a hammer, everything looks like a nail."  Lets not use var as our hammer. Its a special tool for special cases. We don't use ice axes for steak knives do we (even though that would be very manly and barbaric - and hell, kind of fun), so we shouldn't use var for unintended uses.

#    Comments [0] |
 Sunday, March 23, 2008

Beginner Test Driven Development Habits

Having worked on quite a few teams where I've been the lead responsible for helping implement TDD or been an Agile Coach - I've seen a group of habits develop when teams first start utilizing TDD. These are ...

 

1. No test isolation

All functionality that is being tested is in one test. Tests are heavily over specified.

How to fix: Spend some time pairing with the developers that are having the issue. Help explain why we want to break tests apart into smaller units, aka: "UNIT" tests. Let them know that we do not want to test the entire class in one unit test. Just because it can be done doesn't mean it should be done. Ya know, I COULD drive into oncoming traffic, but its just not a good idea. :)

 

2. Failure to recognize the TDD Mantra tddcycle

Most  new TDD'rs will go from Red to Green to - I'm done! Nope. I'm sorry guys, we have one more in that list - Refactor. Let's say it together.  Red/Green/ReFactor, Red/Green/ReFactor :)

How To Fix: Help the developers realize that we want to refactor for a reason. We have a passing test, we know what to expect from our results. Now lets clean up our code, maybe introduce some interfaces, change some variable names, introduce some fields, extract some methods, etc. Doing this allows us to clean up the code as well as have the confidence that our changes did not muck up the expected result. Run the unit tests after you refactor. If it breaks, oops, lets go figure out WHY it broke. We caught the error early, its a lot cheaper now. :)

 

3. The previous lends itself to Insufficient Test Coverage/TDD is my new Debugger

The developers usually will do enough to get the test passing and then move onto the next task. They think of TDD as a new debugger.

How To Fix: Sit down with the developers that have this issue and explain: Just because we can now unit test a method/object and step through it with a debugger doesn't mean that this is the new debugger.  That's not the point. Just because the test passes doesn't mean we're done. Just because your method passes if you pass a valid object into it doesn't mean that its fully tested. What happens if I pass a null object into it? What happens if I pass a new'd up object with nothing instantiated? Have those instances been tested? Have we tested that our objects are interacting as we expect them to? Do we know if the Logger got called? How do we know if we didn't test it?  That its the classic question: How do we know it works, if we don't have a test to prove it?

 

4. No concept of separation of concerns or IoC/dependency injection.

This is not a big deal and I expect it of most new TDD converts. Usually while learning TDD the first few tests do not need DI/IoC, but this is something that will help in the future and will need to be understood to really grasp. This really comes into play when we start separating our concerns and breaking dependencies between objects. The refactoring that takes place here can really get deep into DI/IoC sometimes.

How To Fix: Give them a great intro into interfaces and how they're used. Show them great articles on DI/IoC written by Martin Fowler, Jeremy D. Miller, Ayende, and have them join certain mailing lists such as altdotnet to join in/read the discussions. On that list alone, DI/IoC discussions occur on a daily basis.

5. TDD Complaints

I've seen complaints such as:

    1. It takes too long to write the tests
    2. I write more test code than real code.
    3. The tests are harder to write than the real code.
    4. How is this going to help me get my project done? I can just hit F5 and test it and I can tell if it works or not with my own eyes.
    5. Who cares if it passes a unit test, I'm the only person who works on this project.

How To Fix: This is one of those habits I've seen in every place I've coached. These are classic examples of someone who hasn't "seen the light" of TDD yet. In my experience, the easiest way to help them see the light is to pair with with them while writing unit tests. They will instantly see why the unit tests help them and the team. Every single time I do this I help the TDD newcomer realize that by writing this test they've exposed X bugs that they didn't think about before. It usually goes like this: "Ok, that test passes, what would happen if an empty string was passed into this? Would the DB accept an empty string?" Them: "Oh... good point, I didn't think of that." Instantly lights start turning on. Another thing that works great to help developers see the light is to ensure that you're utilizing Continuous Integration such as CCNET, or TeamCity. Have them create a unit test for a section of code. Check it in. Watch it build and watch unit tests pass. . Then have them change the code (the code which is under test) and ensure it returns a different result. Maybe it returned a user's name, such as "bob", now have it return the users name with some characters appended to the end of it, such as "bob123". Have them check it in, watch the build fail because the unit test failed. Explaining to them that this helps catch errors before the product is live is crucial. Once they have the "Ohhh!! I get it now moment", they won't want to stop writing tests.

#    Comments [0] |