Showing posts with label testing. Show all posts
Showing posts with label testing. Show all posts

Wednesday, March 24, 2010

Eclipse and Mockito

Mockito is great. A big part of it is the syntactic sugar, which relies on using static imports. Eclipse, by default, removes static imports when you use 'Organize Imports' (Ctrl+Shift+O). This saddened me, so I found a way to fix it. Thanks go to this post on static import content assist and the post it links on organize imports. I will repeat both instructions in here in one place.

Part 1: Tell Eclipse Not To Remove My Precious Static Imports
  1. Open Preferences (Window-> Preferences)
  2. Browse to Java -> Code Style -> Organize Imports
  3. Change 'Number of static imports needed for .* to '1' 
  4. Click Ok 
Part 2: Get Eclipse to Create the Mockito Static Import for Me
  1. Open Preferences (Window -> Preferences)
  2. Browse to Java -> Editor -> Content Assist -> Favorites
  3. Click 'New Type...'
  4. Enter org.mockito.Mockito
  5. Click Ok twice. 
Now you can write unit tests with Mockito in Eclipse without issues. You can now type mock and ctrl+space and Eclipse will add the static import for you. It will also leave it alone when you Organize Imports going forward. No more trying to remember not to Ctrl+Shift+O when editing a mockito test.

Friday, November 20, 2009

Practice your TDD

Misko Hevery made a great blog entry Tuesday. He posted a sample project for practicing TDD. We know that Beginners Need Steps, and that's exactly what he provided. Testing is a skill that is not innate - we as developers need somewhere to start.

In his post, he provides a starter project that can be grabbed from a Mercurial repository and used to practice TDD. The basic code is already layed out, including the first few tests. He even describes how to turn on a setting in Eclipse that will run your tests every file save. Slick - I didn't even know that was possible. That is serious TDD.

I consider this a personal testing homework assignment - I encourage anyone reading to do the same.

I will try to remember to post my resulting source & test code when I finish.

Monday, November 9, 2009

Shout Out to Model View Presenter and Passive View

I mentioned last week that I'd talk about GUI testing, so I suppose I should. GUI testing is generally regarded as hard. In my case, I've mostly had to deal with Java GUI code. There are a few things I can think of to aid in testing GUI code (there may be further ways or angles, too, which I'd love to see discussed if so)

1) Keeping code modular and well encapsulated

The usual good coding habits help a lot here. This is mostly the obvious splitting the duties of code (a la various MVC inspired patterns). There are some improvements over standard MVC, though. Model View Presenter, for instance, is really sweet. Currently one in-house favorite is to have a PresentationModel / View, which is a variation of that.

2) Minimize the amount of GUI code to test (make a view that doesn't have any real logic to test)

This is where Passive View comes in. Passive View is pure awesomeness. (why did I ever write views any other way...) There's very little to test if your view doesn't DO anything but display GUI components and have action handler calls. In Passive View, it's illegal for the view to ask for anything. All data is pushed to the view, it does not 'request' anything. The only permitted calls are action handler methods for when GUI components are interacted with. This action handling can even be turned into an interface, so that the view doesn't even have a real reference to the presenter/controller/etc (pattern-dependent).

Your 'OK' button not doing anything is very rapidly found even without automated tests, so as long as the real logic (which is completely absent from the view) is well tested, you are in good shape.

3) Using GUI testing frameworks (like Abbot) that simulate a user. There are similar frameworks for testing webpages...

It is possible to do automated testing of GUIs even if the first 2 items need work or are deemed insufficient. We use Abbot to automate GUI testing of important parts of our application. The tests run the same way other JUnit tests run. Most would deem these functional (not unit) tests, and I agree, because the time impact of powering up a real GUI (especially one you can't disconnect from your system) and physically typing input and clicking buttons is very noticeable.

Generally, lack of encapsulation and too many dependencies are again a real hinderance and bog down GUI testing. If you can mock out or easily disconnect the GUI from the usual, live system, then speed should be less of an issue. So with proper effort invested in 1&2, I aim to get #3 in the general ballpark of unit test times. I don't think that, following 1&2 strictly, I would write a large amount of abbot tests, but I want to try proving it's possible to have nice, isolated and relatively fast GUI tests if you want them. Maybe I'll do some speed/effort analysis on this at some point - because I'm that much of a geek.

Friday, November 6, 2009

More on testing (part II)

In my latest push to test more, I've been learning some things. Namely, just how much testing can show you. Testing really illuminates bad code. Bad code is hard to test. It might not have been that bad, but just some slight rule bending is enough to make code really hard to test.

So, getting back to the Law of Demeter. It's most easily summarized as:
“Only talk to your immediate friends”
It is also summarized as don't use too many dots. i.e. foo.getBar().getSomethingElse(), but dot counting isn't really what it 's about...

At the end of the day, it's just about proper encapsulation if you ask me. Friends to me are direct dependencies, i.e. objects that are relied or operated on.

When a class A needs another object B (or is made to operate on object B), it should need it because of object B, not because of something in another object C that's in B. That violates encapsulation and exposes the internals of B. B then can't be refactored, because A relies on C.

Now, it's reasonable for A to operate on things inside B, as long as that is where they live and they art a part of B. Testing makes the distinction obvious, because if the access is proper, then exercising and testing the code is simple. If the access is stretching further than it should, then testing will be noticeably more work.

Mocking frameworks can make testing easier in these situations, but refactoring is probably still necessary. I found it necessary in some code I was working on this week, though I would call it gentle refactoring. It felt natural, and really wasn't a lot of work. I am still finding the tests hard to write, but I will keep at it.

I'm one day away from surviving writing daily for my first week of National Writing month. It's been a learning process so far. I'm rambling and not really cleaning up my writing yet - it's intentional so I can just focus on writing regularly. Hopefully at some point it will sound interesting.

I am noticing I have a lot to learn, and a lot to write about testing. I will continue to do so, but I think on the weekend I will sidetrack to some general computer stuff. Most notably I want to talk about my latest PC building escapades, and how much it has really restored my enjoyment of computer use in my spare time.

Thursday, November 5, 2009

Szczepan Faber is my bartender

I've known about Mockito for a little while, but I've only just now officially tried it today, and Sczepan Faber (and friends) are now my bartenders, and when it comes to mocking, a nice cold mockito is my new drink of choice.

Wow. Seriously, wow.

The syntax is exceptionally sweet, and additionally quite clever. A coworker and I dived into how it figures out what method to stub today and that alone was enjoyable.

Mockito will definitely be a valuable tool to have in the testing toolbox.

Tuesday, November 3, 2009

More on Testable Code, and the Law of Demeter

I started looking at a simple enhancement task today. Like many simple sounding tasks, when you peer at the 
system and look at what is actually involved, there may be ugly parts. Especially in ensuring testability, as I am committed to unit testing this code.

In my quest to test more (and test FIRST), I looked at what would be required to add the functionality, and specifically, how to test what I was adding.

Here are the issues with testability and excuses I came up with:
  • No unit test exists for the immediate classes in question (shame on me - it's my code) 
  • The code has a GUI - this usually makes testing harder
  • Too many external dependencies!
  • I haven't tested this exact type of code before (aka: I don't know how)
Tonight I'm going to focus on the dependency issue.

Taking a look at my model, it already relied on more external objects than it needed to for the required functionality. The requested enhancement would (if the pattern continued) require further addition of some heavy weight dependencies. Bye bye testability!

Fortunately, I had both the testability presentations still in my mind, and a coworker who had already solved this problem.

The feature in question is for administering users in a system. Among the things being manipulated are name, manager, credential reset, licensed features, and now - a user's preferred currency code (at the end of the day - a String). Great - slap in a few getters and setters, and we're done! Well not quite - currency code lives on a currency unit which is supplied by a unit system, well, which comes from this other big thing. You get the point. If I was lazy, I'd just pass this big other thing to my model so it could do its job. I'm not going to be lazy - I'm going to pay attention to the Law of Demeter.

This model don't really care about the 'other big thing', or the 'unit system', or anything other than that being able to set a user's preferred currency to Australian Dollars, therefore they have no place in this particular model.

Instead of that, my model will take a data source that can give it valid currency codes and set a user's currency code. Just a simple interface with a couple of methods that will be easily mockable for testing. While I'm at it, I'm going to pull out the existing extra dependencies (there was fortunately just one) that weren't needed. Now my interface has four methods, and I don't need any hulking database-requiring objects to get my model moving. A little shuffling here and there, and very little additional code, and my model is now much more easily tested. Suddenly the "I don't know how to test this" feeling has weakened a bit now that my class is simpler.

I want to write further on my take on the Law of Demeter, but it's 11:45PM and I need to submit an entry daily so I'll have to wrap this up tomorrow.

Afterwards, I plan to cover making testing the GUI easier.

Sunday, November 1, 2009

Writing Testable Code

One of the things I struggle with sometimes is how to write testable code. Especially in an existing system that has lots of established code that is difficult to test. The code may have existing tests, but they are heavy, system tests not quick and speedy unit tests. Eventually, writing more tests in the same style just makes the builds take too long to run, and eventually that one new test may requires several minutes of waiting. Tests that make you wait are not productive, and should not be the norm.

This week I found not one, but two good presentations regarding testable code. Firstly (seen @ the UCOSP blog) was a link to the slides for a presentation done by Misko Hevery & Cory Smith at OOPSLA '09, entitled: "Tutorial: How to Write Hard to Test Code" (PDF Google Docs link). There are quite a few slides, and in addition to illustrating bad practices, there are plenty of examples of writing more testable code as well. Highly recommended, entertaining and educational slides.

The second is a project I already knew about, but never got around to trying. Guice. If you haven't used it (or another Dependency Injection library), I encourage you to watch the youtube video on the main Guice page. The presentation itself has general tips on writing more testable code, and towards the end gets into more advanced examples using Guice. The general principles apply whether or not you use it.

I'll post again with further thoughts once I've had a chance to play around with Guice.