Thoughts / Misc: April 2007 Archives

[UPDATE: the final version of this code was added to ZenTest 3.5.0] As continuation from my previous post, I offer a visualization to help clarify things:
Before After
Click the images to see the code in more detail.

The most important thing to understand is that every matrix line from the "after" version like:

matrix :edit, :edit, :edit, :edit, :edit, :e_RO, :e_RO, :e_RO, :e_RO
is an entire page of the "before" version.

I've made some really good progress with the Functional Test Matrix idea. The code compression ratio is phenomenal. I'm writing up a comparison of the two, but without finesse the post would be huge and boring. I'll summarize here as best as I can.

I think most important idea is that high-level reviews or even edits of the functional tests require reading 1 line per action instead of N average lines per action * M edge cases. Very rough estimates show that my traditional functional test writing style weighs in at 179 lines of test for two actions against the following matrix:

setups         :u_w,   :u_r,  :g_w,  :g_r,  :o_w,  :o_W,  :o_r,  :o_R
matrix :edit, :edit,  :edit, :edit, :edit, :e_RO, :e_RO, :e_RO, :e_RO
matrix :view, :view,  :view, :view, :view, :view, :view, :view, :e_NF

Compare that to the 3 lines above and an additional 61 lines of "legos" used to put the matrix together (and, if you want, another 17 lines for the matrix framework itself). The liberal estimate puts that at 2.8:1, and the conservative estimate at 2.2:1. I suspect these numbers to be a bit high and for it to probably move down closer to 2.0:1.

The kicker for me tho, is that once the testing matures, I think we actually settle on the ideal of only really working with the matrix itself, pushing us up to nearly a 60:1 ratio! Like I said, this is rough, so YMMV. Look above. When my client comes to me and says "I think it'd be more secure all read-only errors were not-found errors", I wind up modifying only 4 result codes. If we change our permissions model and add unreadable and unwritable to group, I add 4 result codes and get 4 more tests for free.

A side benefit (from my perspective) is that the functional test matrix itself is high-level enough that it can be read and understood by the business owner or domain analyst. Allowing them to glance at it and immediately point out either missing edge cases or incorrect results.

Functional Test Matrix

| | Comments (1)

This is an idea I've been tossing around for a while. Akin to Ward's FIT, how do you make testing complex specifications with many edge cases clearer?

I have something similar to the idea below that I'm slowly evolving towards this idea. I'm not entirely sold on it, but it does seem to cut down on the amount of code I have to write and how I have to think about it. What do you think? Suggestions?

The Idea:

This is supposed to get us thinking about the various dimensions our testing should address. If there are states orthogonal to each other (eg. readable vs unreadable, logged in vs not logged in) each of those states should comprise a dimension in the matrix. By addressing it this way, we should be able to minimize the amount of setup/teardown code and get full coverage across our actions for all these edge cases and as a result have extremely clear tests.

Example Test Matrix Specification:

setups          :edge1, edge2, :edge3, ...
matrix :action1,  :new,  :err,   :err, ...
matrix :action2,  :del,  :err,    :na, ...
matrix ...

setups:

I envision the setups being a code that combines the different dimensions of edge case state.

Something for a CMS might look like: [df][uga][rRwW] where:

  • [df] for dir/file
  • and the rest is in the style of symbolic args to chmod.
  • lowercase X == Xable, uppercase X == unXable, where X is read/write

matrix:

:new/:err/:del are just examples, they should have semantic info attached to them.

Edge cases specific to an action that fall outside the matrix are regular tests.

How it Fits Together:

Setups stores off the edge cases. Matrix creates a test method for every applicable (read: a non :na result) in the (rough) form of:

def test_#{action}_#{setup}
  matrix_setup_configuration #{setup}.split(//) # global setup
  matrix_setup_#{action} #{setup}, #{expected}  # action setup + execution
  matrix_test_#{expected}, #{setup}             # expected verification
end

My Availability

| | Comments (0)

I'm not really good on the sales and marketing side, but a number of people have been bugging me to go public about my availability, so here it is. I'll be posting this in a more permanent location (linked on the sidebar) once I get it polished up and finalized:

I'm available for consulting on a part-time basis, 10-20 hours a week, at $100 per hour. I'm usually brought in for short-term gigs as a troubleshooter/problem-solver. Probably not worth mentioning, but this page should be proof that I'm better working on backend issues than UI. Email me at: ryand-ruby@zenspider.com.

What I do:

  • Bootstrap new projects.
  • Troubleshoot deep/confusing problems so the main developers can focus.
  • Identify and fix problems to accelerate the development process.
  • Design and implement solid, well-tested, efficient backend code at a rapid development pace.
  • Retrofit or shore up tests.
  • Refactor or reimplement brittle code.
  • Profile and fix bottlenecks.
  • Develop developer tools to improve the development process.
  • Mentor.

What I Prefer to do it with:

  • Ruby (yes, and rails)

What I also do:

  • Java
  • Python (but please no more twisted python!! blech!)

What I used to do and might be bribed into doing again:

  • Smalltalk
  • Perl
  • C/C++/ObjC

Past Clients (ones I can mention):

My Projects:

I also Contribute to:

About this Archive

This page is a archive of entries in the Thoughts / Misc category from April 2007.

Thoughts / Misc: March 2007 is the previous archive.

Thoughts / Misc: May 2007 is the next archive.

Find recent content on the main index or look in the archives to find all content.

Pages

Powered by Movable Type 4.1