Archive for the 'Code' Category

Announcing the JIRA Plugin for Quicksilver

I spend a lot of time interacting with the JIRA issue tracking software – often small tasks that need to be completed ("Add support for x recipe format", "Fix x on the website"). Though I'm fond of the web interface, the amount of clicks required to create a new issue can become tedious.

I'm also a HUGE fan of Quicksilver, so it seemed natural to leverage its productivity-foo to speed up the process.

With that in mind, I'd like to present the brand-spankin' new "JIRA Plugin for Quicksilver".

The following movie demonstrates how to configure the details of a JIRA instance and create a new issue using Quicksilver:

Watch the movie (You may need to control-/right-click on the link and download the movie.)

To create an issue, enter Quicksilver's "text entry" mode (press "."), and type in the information in the following format:

issue summary [: issue description] @ project key [> issue type]

The description and issue type (a number corresponding to the type – by default, a bug is 1, new features are 2, tasks are 3, improvements are 4) are optional.

For example, to create a new issue called "New Issue", in the project "FOO", you would type the following:

New Issue @ FOO

After that, tab across, type in "JIRA" and the "Create new issue in JIRA…" action will appear. Hitting enter on that will create the issue and open a new browser window for the issue.

Download version 0.1 here.

Notes:

  • The JIRA password is stored in the Quicksilver preferences in PLAINTEXT for the moment. I will investigate storing it in the keychain in the future.
  • It will also spit out a bunch of logs into your console. No biggie.

“Avoiding Copland 2010″

John Siracusa has initiated an interesting discussion about automatic memory-management vs Cocoa's retain/release system… I can see the arguments for both sides.

It's handy in Java to not have to worry about releasing objects after using them. It's also neat in Objective-C/Cocoa, at times, as you can *almost* have the best of both worlds with NSAutoreleasePools ("autoreleased" objects are collated into the pool, and either released by the application at certain times, or when you release a pool you created) and retain/release methods. It's also neat when writing a for loop dealing with lots of data, to be able to say "I definitely don't want this hanging around in memory any more! Get rid of it!", without having to wait for the garbage collector to pick it up (and the memory usage going up in the process).

Would automatic memory-management be useful? Sure. I'd spend less time making sure I'm properly retaining/releasing objects, but I'm not going to lose any sleep over it (actually… maybe I am, given the time I'm writing this post). The Cocoa (and related APIs) are great to use, and if I have to put up with "semi-automatic" memory management, then so be it!

On Unit Testing…

So Wil Shipley's post a few days ago about the merits (or lack thereof) of unit testing has enraged quite a few people.

Looking at the comments, there's a bunch of people that agree with Wil's reasoning on face value ("Yeah! Unit testing sucks! It takes up so much time!"), but then you have others who disagree (to an extent). The most enlightening post I've seen on the topic is by Bill Bumgarner, who notes that unit testing was used by the team developing Core Data to make sure the code adhered to the specification (or expected behaviour), as well as preventing regressions when bugs were fixed.

As has been pointed out by many, unit testing is most useful for application "infrastructure", and, with my limited experience, I would tend to agree. Unit testing of the classes that directly handle user actions usually doesn't make sense. However, at the foundation classes, it does. In the Confluence team at Atlassian, we write unit tests (although probably not as often as we should!) for many of the base classes to ensure that they behave as expected. The advantage of this is that should the implementation change, we can run the unit tests and make sure the code behaves as we expect it to! Granted, this is an application deployed over the web, but the same principles can be applied to an application with a GUI on the Mac.

When developing Connoisseur, I had no idea what unit tests were, and as such there have been no tests. Recently, while re-writing some of the parsers, I decided to write tests to chuck recipes at the application and make sure they're parsed correctly (or to an acceptable degree – nothing's perfect). The advantage of this is that if I made a change in the code that stopped the parser from interpreting a certain type of recipe, I would know about it. It took a while to do, but I believe it was time well spent, as I can now determine when there are regressions in the quality of the various recipe parsers, automatically.

Something which Wil didn't mention is automated/functional testing. We use this heavily in the Confluence team (and part of my work has been to write more test cases), utilising jWebUnit. While unit testing is handy, I can more readily see the benefits of using automated acceptance testing (at least for a web application). Over the past two days, I've been re-writing one of the default macros to add support for a feature in the next release. Obviously, backwards-compatibility with the old version of the macro is essential, so I wrote a bunch of test cases that would cover most areas, including testing different parameter settings, permissions, errors, etc. Had I done this manually, actually implementing the new version (and making sure it worked) would have taken forever.

Things on the "normal" application side are a bit different. With jWebUnit, you can simply inspect the HTML source and make sure such and such link is present, some other text isn't present, and so on. With a traditional application, how to you determine that the correct entries are in a table, and that the correct sheet with the correct text appears? One solution I've seen is Eggplant, which looks great for doing such testing, but costs a fair amount (let's just say a one-user license is a little bit more than the most expensive version of Confluence…), and neither Mat nor I are prepared to spend that much at the moment. So automated acceptance testing is out of the picture, for now.

However, as Wil said, there are other forms of testing that are essential to product development, such as user/beta testing. Ideally, the development process could benefit from the use of unit, acceptance AND user testing, to effectively eradicate a large proportion of bugs in the program. This is something that has been lacking in the last few releases of iPodRip and Connoisseur, and something we're working on for the future.

Phew. What a rant. Basically, unit testing has its merits, but should be used in conjunction with user/beta testing and (ideally) acceptance/functional testing.