Test Automation Planet

November 20, 2008

Michael Bolton

Schools of Testing and Schools of Music

There's been a lot of controversy on the schools of software testing lately, in Paul Gerrard's blog here and here and here; in James Bach's blog here and to some extent here, and on the software-testing mailing list. I also had a pleasant chat with Paul Gerrard at coffee break and lunch today at EuroSTAR 2008.

Jonathan Kohl and I did a paper on the parallels between testing and music at CAST 2008; you can find it in the .PDF of the proceedings. Maybe something about music can offer us a way out of the dilemma.

There are lots of ways of approaching music, as a performer, a listener, or a critic. (I use the word "critic" in the sense of someone who tries to understand, describe and contextualize the work, not in the sense of someone who tries to disparage it, although these are often confused.) These different approaches are sometimes called styles, or forms, or traditions. They may be informed by a certain kind of thinking, certain aspects of practice, certain instrumentation. Specific pieces of work and specific composers are considered by their communities (or by others, or by themselves) as exemplars of these styles. Some play music just for fun. Some play on an amateur basis, but are deeply committed to the pursuit. Some play professionally, but as for all kinds of working people, some of the pros may be ambivalent about their commitment to the art. Some people talk casually about the styles, the pieces, and the artists. Others—the critics—are more serious, and study the styles, typically focusing on one or another of them. The quality of their criticism is conditioned at least in part by the ways in which they consider the similarities and differences.

Some artists choose to categorize themselves as practioners of a specific style ("I'm a blues guy"; "I'm a classical musician".) Some artists, not wanting to be pigeonholed, refuse to categorize themselves. Yet categorization happens anyway, sometimes by admirers and sometimes by detractors.

To me, to reject or even to neglect the differences between one kind of music and another is silly, if you're trying to become a better student of the field. Classifications can help to understand the differences and the similarities between one form of music and another—or they can be used to reject some forms. "That's just a bunch of noise!" When her work is labelled that way, the artist has the option to reject the statement outright, essentially ignoring it, or to engage the criticism by providing counter-arguments as to why someone might value this style or this piece. And so we learn.

Within an established tradition in music, there are three rough groupings. Some artists recognize other styles and incorporate them into their work. These tend to be in the avant-garde, which pushes the boundaries of the style to some degree. Other artists tend simply to work within the style, often pretty much ignoring the edges or the roots. Then there are the staunch traditionalists—those who believe that every innovation in a genre after a certain point in history is an accretion and mischief.

So it is with testing. The notion of schools (call them what you will—styles, camps, religions, bodies of thought, cultural frameworks) is a notion that can help us to frame discussion and to identify different approaches to testing in theory and in practice. People can identify context and choices, with the goal of explaining or understanding their own styles or others. There may be controversy between the schools—their adherents, their detractors, and those who have to watch—but the idea that this kind of categorization shouldn't exist, or should be considered prohibited speech, strikes me as silly.

In my conversation with Paul today, Paul compared the use of schools to a kind of bigotry or racism. That risk is there, but like differentiating between cultures, it depends how you intend to use the distinctions. The question is not whether there are differences; there are, they're real, and it can be handy to identify them. I observed that far from being inherently antagonistic, the schools concept could allow us to be more polite to one another. As an example, Paul suggested (not too seriously) that if you're not being context driven, you're stupid. I could agree with that, but it might be more productive to say that if you're not context driven, you might be driven by analytical-school values. This reminded me of Jerry Weinberg's advice that when you think someone is being irrational, reframe your position to think of them as being rational from the perspective of a different set of values.

Have you noticed that some people who are staunch advocates of equivalence class partitioning and boundary value analysis seem virulently opposed to the idea of differentiating between schools of thought?

by Michael (noreply@blogger.com) at November 20, 2008 02:41 PM

November 19, 2008

Test Squad

Issues and Concerns about Watir

These are some observations and issues i noticed using Watir. I am automating the test of a dot net application under IE 7.

This post is still being updated ...
  1. Watir is slow if compared to Selenium. Even when you use ie.speed=:zippy, it's not very practical and components like phone numbers fields like the one in the picture below will crash. Because what ie.speed=:zippy does is actually using the method value= instead of set() and i had some fields crashed because of that. So i didn't useie.speed=:zippy and instead i used ie.speed=:fast and value= only with text_field. And still the playback is very slow relatively. Personally i think the reason why Watir is slow because ruby is a fancy programming language!



  2. I managed to connect my watir script to a datapool. I used ruby/mySQL driver to pull the data from a localhost database, but again the problem is the slow speed when fitching data from the pool. I am not sure if i can consider this a problem in Watir, since it's the case in almost any automation tool i have used.

Please share your ideas if you have any solution for the above issues

by adel (noreply@blogger.com) at November 19, 2008 08:38 PM

Danny R. Faught

How many social networking sites does it take to screw in a lightbulb?

I’m a frequent user of some of the online networking services, but there are just so many of them, I only focus on a few. A recent communication led me down a convoluted trail through several of them.

It started with with a message from a new contact on LinkedIn, saying I might be interested in a webinar titled “James Whittaker - The Future of Software Testing.” Most webinars sound like glorified commercials to me, but this one looked interesting, and I haven’t talked to James in a while. The URL I was given pointed to Facebook. Clicking the link resulted in a vague error from LinkedIn’s redirect mechanism. I copied and pasted the URL and landed on a Facebook event page. It was actually on www.new.facebook.com - I wonder what that is? Anyway, Facebook shows several people who are invited, and which ones have accepted or declined. Some people made comments on that page.

The description says to go to a URL at www2.gotomeeting.com to register (which seems to be functionality equivalent to www.gotomeeting.com, but not to gotomeeting.com, which gives a certificate error if you’re using https). So the Facebook RSVPs seem to be irrelevant. I went to the GoToMeeting URL, and seemed to find where the event is actually hosted. It’s sponsored by uTest.

Okay, so that’s just two social networking sites, a webinar host, and the actual sponsor. But I’m still amused.

The webinar is November 20, and here’s the broken and convoluted trail to get there. Or just go straight to the end of the trail - https://www2.gotomeeting.com/register/313938344.

by Danny Faught at November 19, 2008 05:57 PM

Virtual Lab

VMLogix LabManager - Best Solution from a New Player

VMLogix LabManager recently won the “Best Solution from a New Player” award given by Software Test and Performance Magazine. This was announced in their November issue which you can download here. Quoting from the magazine: “VMLogix LABMANAGER 3.5 took this year’s top spot for Best Solution from a New Player, which we define as a company [...]

by vmlogix at November 19, 2008 05:38 AM

chromatic

Parrot 0.8.1 "Tio Richie" Released!

On behalf of the Parrot team, I'm proud to announce Parrot 0.8.1 "Tio Richie." Parrot is a virtual machine aimed at running all dynamic languages.

Rat Creature #1: Comrade! We are about to feast! Quick, get your fat carcass behind this bush and get ready!

Rat Creature #1: Hello, small mammal.... Could you step in here for a moment? I've got something to show you....

Fone Bone: Can't you show me out here, where I've got runnin' space?

Rat Creature #1: No! No! Please! Step in here -- your friend the dragon isn't around, is he?

Fone Bone: Hey, Ted! Where you goin'?

Ted: You're on yer own, Bone! (exit stage left)

Rat Creature #1: Quick, comrade! Start the cooking fire!

Rat Creature #2: No. You called me fat.

Fone Bone: Ted! Wait for me!

Rat Creature #1: (pulls Bone into the bush) Well, well... Look who's joined us for supper... Go start the cooking fire!!

Rat Creature #2: No. You called me fat.

Rat Creature #1: No?!!! What do you mean, no?!!!

Rat Creature #2: And it's not the first time you've done it either....

Rat Creature #1: Comrade... be reasonable! I wasn't thinking -- I was trying to catch our dinner -- this isn't the time -- I take it back.... you're not fat.

Rat Creature #2: Too late!

Rat Creature #1: Please, comrade! I just want to chop him up for the stew!

Rat Creature #2: And that's another thing. I'm tired of stew! I want to put him in a crust and bake a light fluffy quiche!

Rat Creature #1: Quiche?! What kind of food is that for a monster to eat?! .... Listen, do you think you could come back in half an hour? We'll have this straightened out by then!

Bone: (runs away)

Rat Creature #1: (beat) Why didn't you stop me?

Rat Creature #2: Why should I? You're so smart!

time passes

Fone Bone: (hanging from a branch in a waterfall) Those rat creatures would have to be pretty stupid to follow me on to this frail, little branch!

Rat Creatures: (follow Bone on to the frail, little branch)

Fone Bone: Stupid, stupid rat creatures!! (branch breaks)

"Bone", by Jeff Smith

Parrot 0.8.1 is available via CPAN (soon), or follow the Parrot download instructions. For those who would like to develop on Parrot, or help develop Parrot itself, we recommend using Subversion on our source code repository to get the latest and best Parrot code.

Please note the updated Parrot Roadmap and our goals leading to the 1.0 release.

Parrot 0.8.1 News:

- Implementation
  + added CPAN module Storable 2.12 as a configuration and build dependency
  + removed the pseudo PIR opcode 'addr'
  + added the 'box' opcode
  + fixed 'pop_eh' handling in PIR libraries and examples
  + removed usage of .return for tailcalls (use .tailcall instead)
  + removed 'get_hash' and 'get_array' from Capture PMC and Capture_PIR
  + improved debugger and HLL coordination
  + allowed MMD primitive autoboxing
  + fixed all known memory leaks in PIR "Hello, world!"
  + NCI signatures now JITted on x86-32 platforms (Windows and Linux)
  + made the .const directive take a quoted type name instead of a constant
  + made IMCC more re-entrant
- Languages
  + Rakudo
    - refactored Junctions implementation
    - added "fire and forget" tool to rebase/rebuild/test Parrot and Rakudo
    - updated container/reference semantics
    - added more builtin methods and functions
    - improved support for multilevel namespaces
    - added support for .Str, .succ, .pred in user-defined classes
    - implemented pointy blocks on if/loops
    - increased STD.pm convergence
    - added %*VM hash
    - improved MMD candidate sorting
    - improved integration of Num and Int
    - implemented increment on protoobjects
    - added initial support for MAIN subs
    - added .PARROT method
  + Pipp
    - added some predefined constants.
    - added implemention of the function basename().
  + Cardinal (Ruby)
    - Added initial support for the classes Proc, Continuation, Queue, Dir, File, and FileStat
    - fixed various minor bugs
    - fixed broken Regexes
- Compilers
  + PCT
    - added '.isa' method to PCT::Node
    - cleaned up 'immediate block' handling
    - allowed arguments to immediate blocks in loops/conditionals
    - metaclass objects can now 'add_method'
  + PIRC
    - integrated macro processing in PIRC's lexer
    - integrated heredoc lexer in PIRC executable
    - added preprocess and heredoc-preprocess commandline options
    - integrated the PASM grammar into PIRC
    - added a register allocator to optimize the built-in vanilla allocator
    - code cleanups and documentation
    - added 'make test' target
   + TGE
    - updated to work with new namespace/classname syntax
- Deprecations
  + PARROT_API will become PARROT_EXPORT
  + :lexid will become :subid
- Miscellaneous
  + Documentation
    - updates and additions to the Parrot book (see docs/book/)
  + OpenGL
    - minor fixes to Parrot's base OpenGL bindings
    - converted OpenGL PIR examples to Perl 6 (two complete, one WIP)
    - added simplified OpenGL PIR example for NCI JIT testing
  + Tests
    - further improvements to parallel tests
    - tests no longer leave filesystem breadcrumbs

Thanks to all our contributors for making this possible, and our sponsors for supporting this project. Our next release is 16 Dec 2008.

Enjoy!

by chromatic at November 19, 2008 03:35 AM

November 18, 2008

Object Mentor

SLIM Tutorial

This is a video overview of the new SLIM test system in the latest release of FitNesse

by Uncle Bob at November 18, 2008 07:51 PM

Google Testing Blog

My Unified Theory of Bugs

by Miško Hevery

I think of bugs as being classified into three fundamental kinds of bugs.

  • Logical: Logical bug is the most common and classical "bug." This is your "if"s, "loop"s, and other logic in your code. It is by far the most common kind of bug in an application. (Think: it does the wrong thing)

  • Wiring: Wiring bug is when two different objects are miswired. For example wiring the first-name to the last-name field. It could also mean that the output of one object is not what the input of the next object expects. (Think: Data gets clobbered in process to where it is needed.)

  • Rendering: Rendering bug is when the output (typical some UI or a report) does not look right. The key here is that it takes a human to determine what "right" is. (Think: it "looks" wrong)


NOTE: A word of caution. Some developers think that since they are building UI everything is a rendering bug! A rendering bug would be that the button text overlaps with the button border. If you click the button and the wrong thing happens than it is either because you wired it wrong (wiring problem) or your logic is wrong (a logical bug). Rendering bugs are rare.

Typical Application Distribution (without Testability in Mind)

The first thing to notice about these three bug types is that the probability is not evenly distributed. Not only is the probability not even, but the cost of finding and fixing them is different. (I am sure you know this from experience). My experience from building web-apps tells me that the Logical bugs are by far the most common, followed by wiring and finally rendering bugs.



Cost of Finding the Bug

Logical bugs are notoriously hard to find. This is because they only show up when the right set of input conditions are present and finding that magical set of inputs or reproducing it tends to be hard. On the other hand wiring bugs are much easier to spot since the wiring of the application is mostly fixed. So if you made a wiring error, it will show up every time you execute that code, for the most part independent of input conditions. Finally, the rendering bugs are the easiest. You simply look at the page and quickly spot that something "looks" off.

Cost of Fixing the Bug

Our experience also tells us how hard it is to fix things. A logical bug is hard to fix, since you need to understand all of the code paths before you know what is wrong and can create a solution. Once the solution is created, it is really hard to be sure that we did not break the existing functionality. Wiring problems are much simpler, since they either manifest themselves with an exception or data in wrong location. Finally rendering bugs are easy since you "look" at the page and immediately know what went wrong and how to fix it. The reason it is easy to fix is that we design our application knowing that rendering will be something which will be constantly changing.




























LogicalWiringRendering
Probability of OccurrenceHighMediumLow
Difficulty of DiscoveringDifficultEasyTrivial
Cost of FixingHigh CostMediumLow

How does testability change the distribution?

It turns out that testable code has effect on the distribution of the bugs. Testable code needs:


The result of all of this is that the number of wiring bugs are significantly reduced. (So as a percentage we gain Logical Bugs. However total number of bugs is decreased.)



The interesting thing to notice is that you can get benefit from testable code without writing any tests. Testable code is better code! (When I hear people say that they sacrificed "good" code for testability, I know that they don't really understand testable-code.)

We Like Writing Unit-Tests

Unit-tests give you greatest bang for the buck. A unit test focuses on the most common bugs, hardest to track down and hardest to fix. And a unit-test forces you to write testable code which indirectly helps with wiring bugs. As a result when writing automated tests for your application we want to overwhelmingly focus on unit test. Unit-tests are tests which focus on the logic and focus on one class/method at a time.

  • Unit-tests focus on the logical bugs. Unit tests focus on your "if"s and "loop"s, a Focused unit-test does not directly check the wiring. (and certainly not rendering)

  • Unit-test are focused on a single CUT (class-under-test). This is important, since you want to make sure that unit-tests will not get in the way of future refactoring. Unit-tests should HELP refactoring not PREVENT refactorings. (Again, when I hear people say that tests prevent refactorings, I know that they have not understood what unit-tests are)

  • Unit-tests do not directly prove that wiring is OK. They do so only indirectly by forcing you to write more testable code.

  • Functional tests verify wiring, however there is a trade-off. You "may" have hard time refactoring if you have too many functional test OR, if you mix functional and logical tests.


Managing Your Bugs

I like to think of tests as bug management. (with the goal of bug free) Not all types of errors are equally likley, therefore I pick my battles of which tests I focus on. I find that I love unit-tests. But they need to be focused! Once a test starts testing a lot of classes in a single pass I may enjoy high coverage, but it is really hard to figure out what is going on when the test is red. It also may hinder refactorings. I tend to go very easy on Functional tests. A single test to prove that things are wired together is good enough to me.

I find that a lot of people claim that they write unit-tests, but upon closer inspection it is a mix of functional (wiring) and unit (logic) test. This happens becuase people wirte tests after code, and therefore the code is not testable. Hard to test code tends to create mockeries. (A mockery is a test which has lots of mocks, and mocks returning other mocks in order to execute the desired code) The result of a mockery is that you prove little. Your test is too high level to assert anything of interest on method level. These tests are too intimate with implementation ( the intimace comes from too many mocked interactions) making any refactorings very painful.

by Misko (noreply@blogger.com) at November 18, 2008 10:32 AM

November 17, 2008

Danny R. Faught

Unit vs. System Testing—It’s OK to be Different

My StickyMinds column, Unit vs. System Testing—It’s OK to be Different was posted on October 20, 2008. Comments are still open, and I’d love to get your feedback either on StickyMinds or here. This is a concept that I first explored as a lightning talk at CAST 2008, and then more fully at a meeting of the Fort Worth IEEE chapter this summer.

by Danny Faught at November 17, 2008 08:39 PM

Curtis "Ovid" Poe

Test::Most::Exception - Important, But You Won't Need It

Recently I uploaded the new Test::Most. From the end user perspective, the only real change (aside from being a touch easier to install), is that if you ask it to die when a test fails, it no longer just dies. Instead, it throws a Test::Most::Exception. The vast majority of people will never, ever need this feature. However, our test suite gets a bit tricky at times and we do things like this:

foreach my $test (@tests) {
    my $tests_finished = eval { $test->run };
    if ( my $error = $@ ) {
        report_error( $test, $error );
    }
    else {
        ...
    }
}

Internally, the way we report failures depends very much upon whether or not the tests halted because Test::Most was told to halt on failures, or whether they really died. Now I can just do this in the &report_error sub:

if ( eval { $error->isa('Test::Most::Exception') } ) { ... }

And much grief is saved.

In other news, I've been asked to add timing data to Test::Aggregate and I've thought that prove's state mechanism should possibly be extended to capture aggregated state information. In other words, while I didn't really intend to, I'm writing yet another new test harness. You would think I've learned my lesson after writing the new Test::Harness (also by accident, I might add).

And yes, I've toyed with colored test output for it ...

by Ovid at November 17, 2008 03:29 PM

Object Mentor

!define TEST_SYSTEM {fit:A}

Uncle Bob has been busy with FitNesse lately. If you have been following him on Twitter or if you read his blog post on the subject, then you are aware of his work on Slim.

This post, however, is not about that. It is about something he did to make it possible to execute different tests in different VM’s.

By default, when you click on the test or suite buttons to run tests, FitNesse finds the tests it will run and executes them in a single VM.

If you want to select a particular test runner in FitNesse, you can add the following to a page:
!define TEST_SYSTEM {fit}
Or you could add the following:
!define TEST_SYSTEM {slim}

If you do not define this variable, then fit is the test system used to execute tests, making the first example redundant…almost.

These variable definitions are inherited. FitNesse will search up the page hierarchy to find variable definitions. If you do not define TEST_SYSTEM anywhere in a page’s hierarchy, then that test will be executed with fit. However, if any of the pages above the current page changed the runner to slim, then Slim will be the test runner.

The other thing that you can do is add a “logical-vm name” to the end of the runner. Here are two examples:

On some page

!define TEST_SYSTEM {fit:vm1}

On a different page

!define TEST_SYSTEM {fit:vm2}

All tests under the page containing the first define run in a vm with the logical name vm1. The same is true for vm2.

By default (i.e., you have not defined TEST_SYSTEM anywhere), all tests are run in the same vm. More precisely:
  • When you click the test button, all tests executed as a result of that button click run in one VM.
  • When you click the suite button, all tests executed as a result are executed in the same VM.

As soon as you introduce the TEST_SYSTEM variable, the tests might execute in the same VM or different VM’s.

Conceptually, there’s a default or unnamed VM under which all tests execute. As soon as a page contains a TEST_SYSTEM with the added :VMName syntax, that page and all pages hierarchically below it run in a different VM.

If for some reason you want to have two unrelated page hierarchies execute in the same VM, you can. Define the TEST_SYSTEM variable with the same logical VM name.

Why did he add this feature

I asked him to. He was working on that part of FitNesse so I figured he’d be able to add the feature for a project I’m working on.

It has to do with service-level testing of a SOA-based solution. If you’re interested in hearing about that and the rationale for adding this feature to FitNesse, let me know in the comments and I’ll describe the background.

by Brett Schuchert at November 17, 2008 11:54 AM

November 16, 2008

Teknologika - Bruce McLeod

Hello Rails

After wanting to try it out for some time I finally decided to jump in and give rails a try. I also thought it would be interesting to blog the process.

Installing rails

I run Mac OS 10.5 as my primary operating system, which ships with Rails installed out of the box. Ok so all I needed to do was update the install. Expecting that to be painful I was pleasantly surprised when it was this easy:.

sh-3.2#sudo gem update rails
Updating installed gems...
Bulk updating Gem source index for: http://gems.rubyforge.org
Attempting remote update of rails
Successfully installed rails-2.1.2
1 gem installed
Gems updated: rails

That was the easiest update to any software I have ever done.

Building the first application

Ok I am going to cheat with this one (because Rails lets me) and type one line to get a working codebase:

bruce$ rails helloWorld
create
create app/controllers
create app/helpers
create app/models
create app/views/layouts
create config/environments
create config/initializers
create db
create doc
create lib
create lib/tasks
create log
create public/images
create public/javascripts
create public/stylesheets
create script/performance
create script/process
create test/fixtures
create test/functional
create test/integration
create test/unit
create vendor
create vendor/plugins
create tmp/sessions
create tmp/sockets
create tmp/cache
create tmp/pids
create Rakefile
create README
create app/controllers/application.rb
create app/helpers/application_helper.rb
create test/test_helper.rb
create config/database.yml
create config/routes.rb
create config/initializers/inflections.rb
create config/initializers/mime_types.rb
create config/initializers/new_rails_defaults.rb
create config/boot.rb
create config/environment.rb
create config/environments/production.rb
create config/environments/development.rb
create config/environments/test.rb
create script/about
create script/console
create script/dbconsole
create script/destroy
create script/generate
create script/performance/benchmarker
create script/performance/profiler
create script/performance/request
create script/process/reaper
create script/process/spawner
create script/process/inspector
create script/runner
create script/server
create script/plugin
create public/dispatch.rb
create public/dispatch.cgi
create public/dispatch.fcgi
create public/404.html
create public/422.html
create public/500.html
create public/index.html
create public/favicon.ico
create public/robots.txt
create public/images/rails.png
create public/javascripts/prototype.js
create public/javascripts/effects.js
create public/javascripts/dragdrop.js
create public/javascripts/controls.js
create public/javascripts/application.js
create doc/README_FOR_APP
create log/server.log
create log/production.log
create log/development.log
create log/test.log

The one command creates the complete working application, sweet. Now how do I run this?

Running the rails application

Apparently running the application is just as easy:

bruce$ cd helloWorld
bruce$ script/server
=> Booting Mongrel (use 'script/server webrick' to force WEBrick)
=> Rails 2.1.2 application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
** Starting Mongrel listening at 0.0.0.0:3000
** Starting Rails with development environment...
** Rails loaded.
** Loading any Rails specific GemPlugins
** Signals ready. TERM => stop. USR2 => restart. INT => stop (no restart).
** Rails signals registered. HUP => reload (without restart). It might not work well.
** Mongrel 1.1.4 available at 0.0.0.0:3000
** Use CTRL-C to stop.

Conclusion

So after getting my feet wet, I am definitely keen to have a deeper look in to Rails, so apparently it is time to learn Ruby. And what the heck, I might play around with Watir on the way, just to see how close it’s cousin WatiN really is.

by Bruce at November 16, 2008 07:02 AM

November 14, 2008

Antonio Cangiano

Merb, Rails Myths, Language Popularity and other Zenbits

Zenbits are posts which include a variety of interesting subjects that I’d like to talk about briefly, without writing a post for each of them.

Merb: A few days ago Merb 1.0 was released. Congratulations to Ezra Zygmuntowicz on this important milestone, the Merb community and Engine Yard (who finances the project). Merb 1.0 wasn’t even out yet when some people had already started commenting on the fracturing of the Ruby community that this new framework might bring with this, and the impact that this high visibility “competitor” might have on Rails. I believe that having more than one widely adopted web framework will only benefit the Ruby community. Furthermore, it’s important to remember that this is not a zero-sum game. Ruby programmers are perfectly capable of learning two frameworks and using one or the other, depending on the project at hand. This is particularly true if we consider that Merb, for all of its advantages - and disadvantages - when compared to Rails, is not totally different from its forerunner. If you are an expert Rails programmer, you should be able to become proficient in Merb in very little time. To help with this process, the Merb community needs to concentrate on the documentation now, given that the API is finally stable.

Rails Myths: David Heinemeier Hansson began a series of posts about Rails Myths. I like the idea of seeing common myths addressed straight from the horse’s mouth. Over the past two years, Rails has received quite a bit of backslash and old fashion FUD, so it’s important to set the record straight, whether the myths are entirely fabricated or if there is some element of truth to them. Whether you agree with David or not, it’s also nice to hear two sides of the same story. In fact, at the beginning of my book I debunk a few myths, just to set the record straight regarding what some readers may have heard surrounding the framework. It was a fun part to write.

My Book: Speaking of my book, Ruby on Rails for Microsoft Developers, I’m getting closer to the finish line. I’m about to complete Chapter 9 (out of eleven chapters). The initial schedule I was provided with has been extended slightly so that there will be sufficient time to properly review the content and ensure that it’s up to date with the final release of Rails 2.2. Some people wondered what the “Microsoft Developers” part means. Is it for people that work at Microsoft? Is it for .NET programmers? Is it for people who develop on Windows?

The truth is that “Microsoft Developers” is probably just a marketing term that Wrox selected as a catch-all for of the aforementioned categories of programmers. As an author I’m trying to serve all of them well, by providing a guide that sneaks in much of the Rails culture and softens the migration path by using an Operating System, and to a certain extent, tools that they’re already familiar with. In my opinion one of the major obstacles when switching to, or trying, Rails when coming from the Microsoft world, is the culture shock. The documentation and most books assume that you are familiar with *nix systems and tools, and this can be frustrating for those who are forced not only to learn a new language and framework, but also an entirely new set of tools. As it’s targeted at Microsoft developers, the book obviously makes quite a few references and comparisons to the .NET world, where they fit. This is done so that the many .NET programmers amongst the group of so called “Microsoft Developers” will find the book particularly useful. Yet the book remains generic enough so that it can be used by any programmer (particularly Windows users), even those without any knowledge of the Microsoft .NET Framework or ASP.NET.

Python books: While on the subject of books, I wanted to mention that the final version of the Pylons book is available online. Despite the much less fancy UI, the book pretty much does what the Django Book did in the past. And both are available in print as well (The Definitive Guide to Django: Web Development Done Right and The Definitive Guide to Pylons). Pylons is a Python web framework that can be viewed as a Ruby on Rails clone, in a far greater way than Django could ever be considered.

Another thing I want to mention is that I received a copy of Expert Python Programming. I haven’t gotten to far into it yet, but from what I’ve seen so far, things look good. I hope to be able to read it through, over a weekend in the near future and then provide a proper review. Stay tuned.

Language Popularity: If you take a look at the TIOBE Index, you’ll notice a few interesting things: Ruby has dropped two positions since last year, and it’s now the 11th most popular language in the world. This shouldn’t be cause for concern though, as shown by this Ruby graph. Python on the other hand is increasing in popularity and moved from the 7th to the 6th most popular language. Interestingly, according to the index (the results of which are educated guesses only), Python would seem to be more popular than C#. I find this to be true, in terms of online activity within an increasingly vibrant community, but in my opinion, the job market hasn’t caught up yet. In fact, at least in Toronto, when there’s a Python opening it’s pretty much an event that’s worthy of being discussed on the local Python mailing list. C# openings are much more common. This may be different in Silicon Valley, of course. It would also seem that Delphi has experienced a huge come back, moving from the 11th position last year to the 8th one this time around. It’s hard to imagine that Delphi has had a similar level of adoption as C# and thus has become more popular than Perl, JavaScript and Ruby. Delphi is a great solution for Win32 programming, but I don’t quite believe this overly optimistic outlook. And if this is the case, where are all the Delphi jobs and buzz?

DB2: This interview shows a few good reasons why even smaller and medium sized companies are increasingly adopting DB2. And while the video doesn’t mention it, IBM is coming out with an updated version of DB2 Express-C 9.5. This new version, 9.5.2 or 9.5 FixPack 2, is going to introduce exciting new features, including an engine for full text search.

The Great Ruby Shootout These days you hear a lot of talk about parallel programming. Intel promotes it and despite their bias, it’s plausible that parallel programming will become important as the CPU market heads towards an increasingly larger number of cores, as opposed to focusing on the frequency of said CPUs. In the world of Ruby, this translates into multiprocessing, as opposed to multithreading due to the infamous GIL (Global Interpreter Lock). This means that Ruby will most likely approach the problem similarly to how Python 2.6 did with the multiprocessing module, which is a process-based interface. The obvious exceptions are JRuby and IronRuby, which establish a 1 to 1 relationship between green threads and OS threads.

For the shootout, it would be interesting to see some multithreaded code, so as to get a better sense of how well JRuby and IronRuby compare to MRI and 1.9, when more cores are available. In fact, the long-promised shootout will be performed on a quad-core machine with 8GB of RAM. If Charles Nutter, John Lam, or any of their team members would like to contribute some programs that are able to take advantage of “native” multithreading, I’d be very happy to include them in the Ruby Benchmark Suite, to be used for my shootout.

The repository requires some love and refactoring, since it needs to be split in two types of benchmarks. The simpler one will evaluate the execution time minus the startup time, while the more advanced benchmark will also exclude the time required for parsing and loading modules, classes and methods in the AST. It would also be nice to test each program with variable input sizes and report these results accordingly. Right now I’m very busy with the book, but as I become more available, I’ll start working on this.

Finally, I want to point out a very interesting article about performance and UIs. Slow is indeed a very relative concept, and it’s important to understand how to analyze and respond to the user requirements when it comes to the responsiveness of an application as a user interacts with it.

Hardware: I finally bought a Trackball made by Logitech and the Microsoft Ergonomic Keyboard (Microsoft makes great hardware). I don’t have wrist problems, but I’d like to see how these two affect my extensive computer usage. I plan to report my experience as soon as I’ve had a chance to use these input devices for a while, since I know this is a topic that interests lots programmers (many of whom end up being victims of RSI, and some of the IRS :-P). I also bought a bad-ass color laser printer which is quite handy when you’re a programmer and you are writing a book. I’ll let you know how it goes. What I didn’t buy, but still think is awesome, is the Flip minoHD. It’s the equivalent of an iPod for the world of camcorders. $235 for a camcorder that’s so perfectly compact, and yet that can record in HD, is a pretty sweet deal. I’m considering it for Christmas, assuming it reaches Canada by then.

by Antonio Cangiano at November 14, 2008 11:50 PM

Brian Marick

Agile Development Practices keynote (text)

Update: some might want to skip the introduction and go straight to the guiding values, which are the point of the talk.

I’m going to begin with a revisionist interpretation of the Agile Manifesto.

The Manifesto stirred up quite a fuss when it was published. Programmers and other “worker bees” identified with it, felt that it had been written for them. True enough. But I’m going to point out that it was also a marketing document, a bargain proposed by a new style of team to the business world.

Here’s the shape of the proposed deal. The teams promised the business two things. First, they promised to respond to changes from the business. That’s a fancy way of saying they’d stop whining when the business changed requirements. It’s not that they were admitting that all those years of whining were some sort of unjustified passive-aggressive trick — as many in the business world more than suspected. It’s that the teams claimed they now had the skills and the technology to let them make software soft enough that they could quickly and correctly implement requirements without caring whether they’d been created last week or last year.

Next, the teams promised to care deeply about delivering working software. Again, the meaning of that is a little unclear. The teams were admitting that they knew the business expected the following trajectory from every last project they paid for:

In January, the team says it’ll be done in November. Then they, more or less, disappear from view. They pop up in September to alarm the business by admitting, in a noncommittal way, that there’s “some schedule risk”. In October — one month before the scheduled release date — they pop up again to admit the schedule will have to slip until, oh, just before Christmas. Since nobody in the U.S. gets anything done between Thanksgiving and Christmas, that December date proves unrealistic. Finally in January, system testing can start. According to the PERT chart, it’ll finish by the end of the month…

Except testing… finds bugs! Bad bugs. Show-stopper bugs. Fixing them has pushed the release into February. Well, March, actually. That’s when the product finally limps into release.

That slow-motion train wreck is what the business has come to expect. A long wait, with disappointment at the end. So promises of working software don’t mean a lot to the business. They don’t trust their team.

But the Agile Manifesto gives a different meaning to the phrase “working software”. What Agilists mean is that if the project starts in January, the business can — indeed, must — expect them to pop back up with working software no later than February. (I’m going to assume a one-month iteration, because it makes for prettier slides, although two weeks is much more common these days.)

Working software means software that the business could — if it wanted — put into actual use. The software does at least one thing — one thing chosen by the business — that has value.

Or, if the business doesn’t want to put the software out for use, they can still try it out — hands on, unscripted — to see if it is salable and convince themselves that the team is making progress. The team’s no longer asking for trust, they’re providing evidence. (Which of course is an excellent way to build trust.)

This process, the Manifesto promises, could proceed month after month after month, stopping when the business decided it had enough value or at any arbitrary date it chose.

That progression of steady increments of value seems pretty implausible. But — the Manifesto claims — it can now be done because teams now have the skills and technology to do it.

That’s one half of the bargain. To make the whole deal work, the business has to do some things in return. First, they have to talk to the development team. And “talk” actually means spoken conversation, preferably face to face, and surprisingly often. Actually, let me highlight that. The amount of communication required will surprise the business even after they think they’re prepared for it.

The second of the business’s obligations is implicit in some of the lines in the Manifesto. The unspoken message is don’t “help” us by telling us how to develop software. We — the team — realize that you — the business — have been scared because our work was so invisible. So you put in checkpoints (like requirements reviews and architectural design reviews) along the way to get early warning that things were going off track. But that didn’t work. In fact, in a perverse way, it made things worse.

The dirty little secret is that the process, the documents, always hindered the team’s ability to respond to changing requirements. Trying — and failing — to reduce one problem increased another. However, we now have the skills and technologies to deliver frequent releases of working software — which is better evidence of progress than documents that talk about what the software will be when we finally get around to producing it. So that was the deal. At first, not too many businesses took it. But now lots have, as witness the existence of this conference.

So the story of the manifesto is over, really. The time for marketing is past. Now what teams have to do is execute. Here, the news is not so good. A lot of teams execute poorly. Helping you avoid their fate is what this talk’s about.

First, though, you’ll notice my emphasis on teams. Teams are what I know. The kind of consulting I do involves embedding myself into teams and helping them out. While there’s lots to be said about making the enterprise safe for Agile, or for making the enterprise agile, or for doing other things involving the word “enterprise”, I’m not the person to say those things. The person to say them is David Anderson, who — fortunately for you — will be giving a keynote on Thursday, making our talks nice bookends for the conference.

Now, given what I’ve said before, you might expect that I’d be touting particular skills and particular technologies. I’m not going to do that, but I hope you sought them out in the tutorials, will keep seeking them out the next two days, and realize that your learning can’t stop with this conference. Skills and technologies are essential. But people know that. So, instead, what I’m going to talk about are guiding values.

Why am I going to spend your time on that topic? It’s because many of the problems I see are due to teams giving into temptation. Values are what keep us on the straight and narrow path in the face of temptation. Teams that have strong internalized values will stick to good Agile practices — and get good Agile results — while teams without guiding values will drift into the ditch.

I’m using “temptation” in a broad sense. For example, I include allowing yourself to be bullied as, most often, a giving into temptation: the temptation to be weak, to play it safe. For that reason, I’m going to name the first value courage. I’ll illustrate courage with a story. I heard it from Ken Schwaber as a description of the kind of person a Scrum Master should be. Once, there was a software team working in cubicles. They didn’t like working in cubicles, an entirely sensible attitude. They wanted an open workspace. That makes a lot of sense, given the amount of communication that goes on between the business and the team and among the team members. However, the furniture police forbade it. Company policy was cubicles, and company policy could not be changed for a single team.

The team went through the usual lengthy arguments, and — as usual — company policy prevailed. Until, one weekend, the Scrum Master disassembled the cubicles and created an open workspace. Come Monday, she announced that if the cubicles were restored, she would immediately resign. That’s courage. That’s a Scrum Master. The job of the Scrum Master is to move immovable objects for the good of the team.

Courage as a value was not present in the Agile Manifesto because that value wasn’t relevant to the sales job. The next value, working software, was present because it’s so important. As a guiding value, it says that if you don’t know what to do, if you think you’re going astray, always err on the side of getting some software doing something that someone can look at. I don’t quite have a story to illustrate that, but I do have a guideline from Kent Beck. As you probably know, people — and especially programmer types — are prone to long, long design discussions about what to do next, about what the appropriate approach should be. A great many of those discussions are wasted time. The fewer facts people have, the harder they argue, it seems. So Beck made up a guideline. Here it is: No design discussion should last more than 15 minutes without someone turning to a computer to do an experiment.

The assumption underlying this guideline is something like this: Humans with their experience augmented by watching — or writing — running code, are smarter than humans alone. Or, perhaps, humans + running code are smarter than humans + time. I’m convinced that books could be written about this worldview. (Actually, they have been — they just don’t mention software.) For now, though, I’ll stop with the guiding value: whenever you’re doing something that’s starting to the immediate making or observing of running code, find a way to irritate you, and that something does not involve add working software to the mix.

Now, there’s a word I just used that I want to go back to, “irritation”, because it’s a bridge to the next guiding value, ease.

Let me start my explanation with a dead philosopher. This [picture] is Martin Heidegger, a truly odious man, but someone who coined a useful distinction. Consider the act of hammering. There are two ways you could experience the hammer. It could be ready-to-hand. In that case, you don’t think about the hammer — you think about hammering. You’re not really conscious of the hammer at all. You’re conscious of the goal, the object of the task — in this case, moving the nail. On the other hand, the hammer could be present-to-hand, in which case you’re constantly aware of the hammer, typically because there’s something wrong with it, putting the goal at risk. Maybe the head’s loose, so it feels like it’ll fly off if you swing the hammer too hard. Because of that, you constantly have to attend to something that’s normally automatic (or ready-to-hand). You’ll always be feeling the hammer present in your hand.

Here’s another example: surgery. I’m told by a surgeon that, if you have a good surgical nurse, you just reach out, maybe vocalizing what you’re thinking, and the right instrument just appears in your hand. It’s ready-to-hand. You focus on the operation, not the tool.

Suppose, in contrast, the surgeon had to search for the right instrument in something like our junk drawer. Now the surgery is made less easy by the present-to-hand-ness of some peripheral activity.

Here’s an example of peripheral activities in software.

I needed to fix a particular bug. To reproduce it, I had to find a Windows Vista machine, but they were all allocated to other people, so I had to upgrade from Windows XP. To do that, I needed more memory, so I had to buy memory, but that meant I needed to get approval from my manager Frieda, but she was angry with me because of a little incident that was still fresh in her memory, so I had to find some way to, uh, even out her opinion of me by delighting her, perhaps with a present. I remembered she was knitting an old-style Dr. Who scarf using rare and exotic animal hair, which is how I ended up at the zoo, shaving a yak.

The phrase “Yak-shaving” has entered the software jargon. One online dictionary defines it as:

Any seemingly pointless activity which is actually necessary to solve a problem which solves a problem which, several levels of recursion later, solves the real problem you’re working on.

This kind of thing happens in software all the time, and it kills productivity.

A characteristic of high-performing Agile teams seems to be how much they value ease of work. So, for example, someone working in some code that’s… awkward… will spend a little time making it easier for the next person. If the build keeps breaking, someone will do a little error-proofing to make it harder for people to break the build. If exploratory testing requires too much tedious manual setup, a programmer might put a shortcut in the app for the testers. And so on. All this is a good example of how a guiding value works. It’s always a temptation to skip doing something in the short term that pays off in the long term. But if you believe, down to your core, that you deserve a pleasant work experience — that your focus on your task should not be diverted by the present-to-hand-ness of everything you want to bring to bear on that task — then your software will get progressively easier to work with.

That attitude counters a problem I sometimes see in new Agile projects. They start out with a burst of productivity. They’re actually delivering software! Each and every iteration! The business is ecstatic. But as time goes on, the trend line is toward less and less value per iteration. The software is becoming rigid, just like all the proponents of Big Design Up Front told us it would.

I believe that if you attend to the ease of your moment-to-moment work, your whole project will be pulled toward the the malleability or softness that’s essential to delivering on the Manifesto’s promise.

This kind of malleability I think both allows and is built upon being reactive. That’s odd, since it’s not respectable to be reactive. We’re supposed to be proactive in all things. So let me tell another story.

I needed help with a persistent problem. I’d have planned out a certain path toward a coding goal, and I’d have coded some way along that path when I realized things weren’t working out — I was getting irritated, unsure of myself. Now — having been taught something by the working code I was writing — I saw a new, better path that I should have taken. But to take it now, I’d have to undo some of what I’d done, which is fairly error-prone. Of course, version control systems let you take a snapshot so that you can automatically and flawlessly jump back to a previous state of the code. The problem was, I never made snapshots at the right places, so I didn’t have the right places to jump back to. I asked Zhon Johanson, a better programmer than I, how he decided when to take snapshots to back up to, and he surprised me by saying “I never back up. I just bend the code toward the better solution.”

I hear this metaphor of bending a lot. Rather than spending too much time predicting the future, you take a stab at it and react to what you learn from writing and running code, always flexibly moving toward the goal.

The Agile belief is that — on average — this being reactive in an uncertain world where you must constantly respond to change, wins over priding yourself at being proactive. This is sometimes referred to as waiting until the last responsible moment to make a decision. Of course, knowing when the last responsible moment is, is a matter of skill. So is knowing how to write software that’s soft enough that you can keep pushing the last responsible moment later and later, closer to release. I want to show you an example of such a skill, because it illustrates another guiding value, fast feedback — getting those little twinges that tell you you’re on the wrong track, that it’s time to react.

In school, we were taught to first build infrastructure. Once you got that done, you add the features — pop pop pop — which ought to be pretty easy now, because you took the time to get the infrastructure right. Hmm… “Took the time” seems like a different thing than “fast feedback”. Let’s look at what “taking the time” means.

You might spend three weeks of a month-long iteration doing infrastructure. Only after that do you implement the first feature. What might that implementation tell you? It might tell you that you got the infrastructure wrong. But now you’ve wasted a lot of time. You’re so far off track that bending toward the solution is too hard. You have to backtrack.

Or, maybe worse, it’s only when you finish the first feature that you get to ask the business “is this what you meant?” From their answer, you might discover you have a fundamental misunderstanding of what they were getting at. But now it’s kinda too late — the end of the iteration is upon you. No time to finish what you promised you’d do for them in exchange for your princely salary.

Infrastructure-first development is a recipe for sudden big surprises that make you… the business… your family and friends all doubt whether you really know what you’re doing.

For that reason, Agile teams usually develop differently. I’m going to show you an example, but first a note: Real Agile development is like the drumming you heard at the beginning — it consists of different threads and themes, each moving at its own cadence, but all working together and synchronizing periodically. One of the problems outsiders often have with Agile is that it looks so disorderly, but from the inside you can see how everything meshes.

To avoid confusion, I’m going to show the new-style development in a simplified, serial form. The team starts with one feature. They finish it. They rush off to the business representative — the one who’s talking to them so frequently — and they get the feedback they crave.

Now they add a second feature. But before they go rushing off to show that to the business, another value takes hold: ease. They’ve probably made the code less easy to work with, in no small part because there’s too much of it. They’ll find that the two features have some things in common, and can share some code.

Now the code is easier to work with. There’s been a slight delay before showing the second feature to the business representative — a slight delay in feedback — but it’s worth the cost. (There are always tradeoffs between values.)

This process continues until the end of the iteration.

What’s interesting is that — if you have the skill to develop software in vertical slices and to generalize by removing duplication — you can end up with an app with an infrastructure. In fact, an infrastructure that looks like it was designed by a fantastically good designer who built exactly and only what was needed by the feature set, with no wasted motion at all.

That’s a nice result. You get to the same place via fast feedback route, but with less danger along the way.

But still, we’re talking about feedback cycles perhaps days in length. To a fast feedback addict, that kind of feedback is scarily slow. What’s more comfortable is feedback every few minutes, as you get with test-driven design. If you have this skill, you describe what you want to accomplish in, say, the next five minutes, then you write the code to accomplish it, then you ask the computer to check whether you did what you said you’d do. This kind of fast feedback, measured in minutes, is what Agile people value, and they will constantly be pushing for faster feedback. I believe that, in doing so, they’re often showing how much they value naiveté, a sort of foolish innocence that willfully denies the idea that software has to be rigid.

I realized the power of naivete back when test-driven design became popular. I’d had extensive experience teaching programmers to unit test in the early-to-mid 90’s and also experience with other kinds of test automation. Based on that experience, I decreed that test-driven design would fail. In particular, I predicted that test suites would not be maintained, that almost all of them would be abandoned after no more than two years. And so would test-driven design — it would be abandoned — just as the last fad for programmer testing had been.

The reason, I said, was that changing test suites to match feature and code changes would be too much work. Well, I was wrong. Way wrong, as it turns out. The interesting question is why. What happened that I hadn’t imagined would happen?

What happened was that the programmers looked at what made unit testing irritating, difficult, and unmaintainable. It was the structure of the code (which I’d always assumed was just part of the unchangeable fabric of the universe), so they changed it. They changed the way they programmed because they demanded ease and fast feedback. It was as if they believed that software — including tests — wants to be soft, wants to be maintainable, and all that’s required is to discover the right skills and technologies to unleash that latent potential, to let that malleability out.

This sort of naive utopian attitude works out amazingly often — when you value malleability enough to make the effort, and when you’re naive enough to try what experience — and the experienced — tell you can’t possibly work.

This naivete extends to more than just software. As an example of it, I’ll use another value, visibility. In some sense, visibility is a consequence of fast feedback — there’s no feedback without new information, and it doesn’t even make sense to talk about new information that you can’t see. But Agile teams tend to make visibility spill over into outright exhibitionism. One reason is that it’s often the case that the mere exposure of a problem is enough to see it solved.

For example, there was a team who believed in pair programming — having programmers work in pairs to write code. What they noticed was that certain people tended to work together over and over. Intellectually, the team agreed that’s a bad habit because it inhibits the diffusion of knowledge, something pair programming is notably good at. But knowing something intellectually and acting on it are two different things. They could have solved the problem prescriptively, by making a schedule that explicitly mixed people up. Instead, they just made the problem visible by putting up this chart. All people had to do was tick off the right cell on the chart whenever they worked with someone. The gaps in the chart made their bad habits constantly obvious. It was what Alistair Cockburn calls an information radiator. And that alone was enough to increase the diversity of their pairing. No mandates required.

There’s an implicit assumption here, one about humans, not software. It is that humans, not just software, can be soft, malleable. I think that’s important. You see, the dominant way of thinking about change is that people are so set in their ways that major change requires a crisis — and certainly many organizations switch to agile because of a crisis.

However, the agile attitude seems to deny the necessity of the crisis, the big fuss, and all the techniques needed to shepherd people through the crisis to improvement. Just make bad habits visible enough. The pressure of constant visibility will make you lay those habits aside, and — over time — what you do instead will themselves become habits, but this time good ones. And, over time, this collection of changes can grow great team members and great teams, exactly in the way that the product grows smoothly from something barely functional to something to be really proud of.

I like this emphasis on steady growth over crisis-driven change, no matter how naive and utopian it seems, because it’s getting toward the last of the agile values I want to talk about, one so out of place, one so shameful, that I barely dare utter its name:

joy

Here’s the thing. If you talk to the people who wrote the Agile Manifesto, eventually most of them will make reference to that one great project, the project that made them think “this is the way software ought to be done.” And the fact that the way it ought to be done was hardly ever done is what made them into evangelists for Agile Software Development.

It was such a pleasure, back in my early days of Agile consulting, to go on a gig and hear both programmers and business people say “this is the greatest project I’ve ever worked on”.

And that’s what worries me. As Agile is becoming widespread, as it’s taking hold in larger and more mainstream companies, I’m starting to hear a different reaction: “At least my job doesn’t suck as much as it used to.”

[Imagine a more impassioned voice.]

Ladies, gentlemen, and others, this is not a lofty goal. I think you deserve better. I think that if you have the courage to frankly bend your work in a joyful direction when you have that choice — while still always, always producing working software at frequent intervals — you can do better than a job that doesn’t suck.

However, I’m envisioning your boss asking you what you got out of the conference, and you replying “Joy!” Joy’s too embarrassing to mention in a business setting. So, which of the other guiding values would I like you to concentrate on?

It’s ease. As I travel around different projects, I see them spending their time shaving yaks, solving — but just for today — problems that are keeping them away from solving their real problems. I see them using tools — or skills — or technologies — or techniques — that are always, always going to be awkward, but not being naive enough to try to fix them. And I see them thinking that their environment — the context of their work — 300,000 lines of legacy code — those damn DBAs — the furniture police — this company’s implementation of Sarbanes-Oxley — are all something that they have to put up with, something they’ll be driven by, rather than something they can and should change.

I know high-performing Agile teams would not put up with that. I know they would immediately start adding ease into their work. Do I know that they’re high-performing teams because they add ease to their work? No. I believe it, but I can’t prove it. You can’t either, but you can try leaning toward ease, bending toward ease, and watch what happens.

If what you see — and make visible — are signs that the combination of the team and the code are getting steadily better at producing value, I think the business has no cause to complain that your work seems too smooth — that you’re not struggling — that you seem to be having a good time.

Remember, it’s part of the Manifesto’s original deal that the business doesn’t tell you how to make software, just as you don’t tell them that the features they asked for are wrong and so you’re going to give them different ones.

I feel strongly enough about ease that I’ve made up some posters and brought some here to give you. They’re down front here. If you don’t get one, but want one, send me me mail and I’ll send you a poster — free — until I either run out or get tired of going to the post office.

With that, I thank you, but we’re not going to have quite the usual question period now. Instead, I want to get together a little panel of people who know more about Agile than I do, so that they can tell me what values I missed, or what values I included that don’t belong, or tell stirring stories of teams putting values into use.

Jeff Patton, come on down!
Rachel Davies, come on down!
Linda Rising, come on down!
J.B. Rainsberger, come on down!
Antony Marcano, come on down!
David Hussman, come on down!

by Brian Marick at November 14, 2008 05:45 PM

chromatic

Perl 6 Design Minutes for 12 November 2008

The Perl 6 design team met by phone on 12 November 2008. Larry, Allison, Patrick, Jerry, Will, Nicholas, Jesse, and chromatic attended.

Allison:

  • we have two sponsors now, BBC and ActiveState
  • starting conversations with a few others
  • it helps to have two already
  • mainly focused on the IO milestone milestone
  • will merge back in two stages
  • stage one is getting the new IO system working
  • you can use it as an object
  • adds just one test file
  • I can have all of the different architectures report any failures with that test file
  • will merge in the bigger change later
  • though it's a simpler change
  • replace calls to the existing system with calls to the new system
  • hope it'll be a smooth transition
  • fixed up some calling conventions stuff last night for Andrew Whitworth
  • some pieces weren't working for him
  • committed a small patch to fix them, and explained it

Jerry:

  • the first Parrot Developer Summit is this weekend
  • for people who don't know about it, it's too late to attend
  • there may be a dozen or so of us meeting
  • intent is to hammer out a roadmap for 1.0
  • lots of questions on the channel and mailing lists about when there will be Parrot 1.0
  • good, I suppose

Patrick:

  • Christmas Eve!

Jerry:

  • they've given up asking about Perl 6

Jesse:

  • good!

Jerry:

  • I don't have an answer yet
  • but our work this weekend will let us decide what we need to release 1.0
  • also had a grant approved
  • designing and implementing Perl 6 command line syntax
  • already started the work
  • researching other dynamic languages and compilers
  • most languages have just grown their syntax over time
  • it's kind of messy
  • have put together some ideas
  • discussed them with Larry
  • expect that to continue, until I have a design document that I can send for review
  • then I'll move on to implementation
  • all laid out in the grant proposal on TPF's site

Jesse:

  • expect me to harass you occasionally

Patrick:

  • things are going well
  • lots of additions to Rakudo this week
  • I fixed the string semantics
  • classes can override how objects report stringification
  • Jonathan, Jerry, and I fixed Rakudo's container semantics
  • it does references correctly
  • fixed a lot of bugs and closed a lot of tickets
  • Jonathan started and I finished getting pointy blocks to work on flow control statements other than for
  • waiting for answers on repeat while and repeat until

Larry:

  • me too

Patrick:

  • when one of us gets the answer, he should let the other one know
  • completely refactored Rakudo's junctions
  • worked on the assignment metaoperators, such as += and *=
  • work correctly on protoobjects
  • I'm refactoring those now
  • will cause regression in one test that doesn't work right anyway
  • Rakudo is now over the 4500 passing test mark
  • we should get quite a few more over the next week or so
  • Jonathan and I will continue closing things out
  • worked more on the design of lexicals
  • continuing to update the document on my website
  • need to figure out autoclose in my head
  • Jonathan and I will hack on that this weekend
  • I could use his expertise in Parrot internals
  • also had a grant approved

Larry:

  • went to the hackers conference this last weekend
  • high point was teaching Don Knuth how to decode his Korean email

Jesse:

  • I thought he had no email!

Larry:

  • refactored the compile-time variables
  • there are no version-specific ones remaining
  • now $?OS, $?DISTRO, and $?VM variable
  • generalized matching against pairs to call a method corresponding to the name on whatever the object is, matching against whatever the argument is
  • sort of inside out as to what named arguments in BUILD routines do
  • refactored the :pair-named methods
  • they were kind of grungy anyway
  • thinking about whether strings ought to have methods like .r and .w and .x
  • or whether you ought to coerce to some sort of File type

Patrick:

  • I lean toward coercion

Larry:

  • everyone does
  • I just want to think it through
  • decided that .perl isn't special to junctions
  • if you use it on one, it autothreads
  • if you stringify that junction, it produces a result as if you'd done .perl on the whole junction
  • stringification on a junction produces Perl-style syntax
  • if you smart match a hash against a pair pattern, it tests the key and the value for matching
  • factoring out various amounts of boilerplate from the Perl 5 emitted code
  • simplifying code
  • fixed bugs with node wrapping
  • confused people looking at ASTs
  • chopped out TRE
  • discovered that my stupid LTM emulation ran twice as fast as the TRE code
  • that was eye-opening
  • STD now recognizes ::T as defining a valid type for later in the same scope
  • did some work to set up the infrastructure for STD to handle lexical scopes
  • nested pads
  • should have declarations in the right scope
  • part of the motivation
  • besides better error handling
  • set up a mechanism to define a prelude
  • freeze the lexical environment for the prelude
  • then slurp that up into STD
  • mundane functions and operators will probably end up there
  • have most of an implementation of a trie engine
  • that'll replace my stupid LTM
  • should evolve eventually into a full DFA
  • almost works
  • should run faster
  • and cut down on the on-disk cache
  • for various definitions of "should"

c:

  • mostly fixing bugs
  • trying to keep blockers from blocking people
  • adding a little polish here and there to make people work better
  • thinking about our release process post 1.0
  • will talk about that this weekend

Will:

  • spending most of my time deleting things from Parrot
  • ripping out deprecated features
  • everything that's in there, some goes back to 0.5
  • but everything in there now we can rip out before the next release
  • sad that I'll miss the summit this week

Nicholas:

  • I'm the new grant manager for Dave Mitchell doing 5.10.1
  • announced the end-of-life for 5.8.x
  • surprised that no one told me I couldn't say that
  • if the Parrot Foundation is capable of raising money from people, how come TPF isn't?

Allison:

  • I tried to do something similar for TPF four years ago
  • it was very uncomfortable for the Perl community
  • lots of pushback
  • they wanted guarantees that no company would have control over the development of Perl

c:

  • no one has control over the development of Perl!

Allison:

  • also the amount of money required for Perl 5 is much larger
  • it's not about money for Parrot
  • four memberships for Parrot is enough to push toward 1.0
  • we're a small project

Jerry:

  • have Perl 5 releases been sponsored before?
  • seems like a good thing

Jesse:

  • last week in China for the Beijing Perl Workshop
  • it was a lovely workshop
  • chatted with a lot of people about the state of Perl 6 and how they could get involved
  • offered to make lots of introductions
  • haven't taken anyone up on that yet
  • the Perl problem in China is that they're having a hard time finding competent Perl hackers
  • people are afraid to learn Perl because that'll make them unpalatable to the workforce
  • universities only teach C
  • people study on their own to learn C# and Java
  • most of the hiring firms really want C# and Java from their developers

Patrick:

  • in Rakudo, over the past week, I'm seeing lots of segfaults in different places
  • suspect it might be something that Jonathan and I did
  • have no clue where to start looking
  • it shows up in the regression suites
  • can point you to specific instances of things that fail

Will:

  • I can help narrow it down to PIR if you have a specific test that fails

Patrick:

  • they really float around
  • showed up in the assignment tests this morning
  • a couple of revisions later, they don't show up later
  • only some of them does -G help
  • the weird one this morning
  • if I run it from Parrot with the command line, I get a segfault
  • from the test harness, I don't
  • that seems backwards

Allison:

  • the test harness has more strict flags turned on

Patrick:

  • at one time, it used a different runcore

c:

  • if there's a short PIR test case, we may be able to do a binary search

Patrick:

  • it's hard to give a short PIR case
  • the segfault moves around so much

by chromatic at November 14, 2008 07:10 AM

Elisabeth Hendrickson

The WordCount Simulation

I’ve mentioned my WordCount simulation here before, and some folks have expressed curiosity about it. I started writing a blog post about it, and quickly realized that it would take a whole lot of blog posts to tell all the stories I want to tell. So I’ll start by explaining the simulation in more detail, and in subsequent blog posts, I’ll tell stories. Some will be amusing little anecdotes. Others will be tragic tales of woe. You’ll laugh, you’ll cry…oh, never mind. Let me just describe the simulation.

So this is the simulation that I use in my Agile Testing class, as well as in other contexts where I want to teach lessons about increasing Agility. The mechanics of the simulation itself are very general: the simulation models the organization of a software company. It just happens to work really well for making Agile concepts very visible, and visceral.

At this point WordCount is a mature simulation: I have honed and refined it over the last several years, and have run it countless times. The simulation requires a lot of moving parts. Just printing the supplies to run the simulation can be a chore. It involves 26 files whose contents are printed on 5 different colors of index cards, 5 different colors of paper and cardstock, and 2 different sizes of stickers. Fortunately for my sanity, I now outsource most of the printing work to a local printer. (Though I swear I can hear the manager groaning when he sees me walk in the door.)

All those moving parts support a relatively simple organization: WordCount, Inc. is a fictional company that makes word counting software. Each participant chooses a role within the company from the following descriptions:

The Product Managers interact with the Customer (played by me or a co-instructor/co-facilitator), define the product, and write requirements on blue index cards.

The Developers turn the requirements from the Product Managers into executable instructions (“code”) on green index cards. The code is then installed on the Computer.

The Testers design test cases on yellow index cards and execute them against the code installed on the Computer by submitting input on white index cards, and receiving output, also on white index cards. Of course, not all input can be processed. If the Computer cannot process the input, it throws a catastrophic error on a purple index card. This usually prompts the Testers to write a bug report on a red index card.

The Computer follows the instructions that the Developers wrote on the green index cards (the “code”) to take the input on the white index cards and process it to generate output, either word counts on a white index card or an error on a purple catastrophic error card. Multiple participants can play the role of the Computer, but the Computer team must coordinate their efforts internally. As you can imagine, sometimes different participants playing the role of Computer interpret the code differently, and give different output for the same input. This inevitably leads to tremendous confusion among the Developers and Testers.

The lone Interoffice Mail Courier (there can be only one) delivers messages and Project Artifacts between groups.

The Observers watch the interactions and share their observations with the group during debriefs. They’re not really part of the company, but they are active participants in the simulation. I usually hand one of the Observers a camera so we have photographic evidence that we can reflect on later as we distill lessons learned from the simulation to apply in the real world.

Throughout the simulation, we work in rounds. So we work on the simulation for 15 minutes, then pause to hold a mini-retrospective in which we reflect and adapt the process to increase Agility.

When we start, there is an existing process in place that resembles a very traditional organization with groups working in silos and very constrained communication. The process explicitly defines responsibilities and communication paths by specifying things like “Communication between Developers, Testers, and Product Managers occurs only through Interoffice Mail,” and “Only Developers may create or modify Code.”

Each group starts with an initial set of artifacts. So the Product Managers have notes from their fictional predecessor’s conversations with the customer, the Developers and Testers have an initial set of requirements, the Developers and the Computer have version 0 of the code, and the Testers have an existing set of tests.

As we begin the simulation, I explain that: as the Customer I desperately need their word counting software to run my business; I have been promised a delivery of the basic word counting system Real Soon Now; so far nothing has been delivered to me. I also make it clear that the more features they ship, the more money they make, and that their goal should be to maximize revenue.

We then work for 15 minutes.

In a typical first round, Product Managers work furiously to produce requirements on blue cards while Developers frantically write code on green cards and Testers crank out test cases on yellow cards. Pens go flying as participants scribble madly on colored 3×5 index cards.

The Interoffice Mail Courier stands by, ready to deliver messages, but typically only has to deliver a handful. One Interoffice Mail Courier was so concerned about the potential volume of mail that he recruited an assistant. They both stood idle for most of the first round, bored. Similarly, the Computer is also usually idle for the first round, and often starts throwing errors just to amuse itself. The Product Managers, Developers, and Testers are so busy producing artifacts that they don’t have time to communicate or even execute the software that already exists.

When we debrief the first round, the Product Managers, Developers, and Testers often report feeling stressed, pressured, and frustrated while the Interoffice Mail Courier and Computers report being under-utilized, idle, and bored.

But all that stress and self-imposed pressure doesn’t yield success. As of today, no group has ever made money in the first round. No group has even come close. In fact, out of all the times I have run this simulation, only one group has ever managed to demonstrate the software to the customer during the first round.

And yet some managers look at the efforts of the Product Managers and Developers and Testers in the first round and see focused productive work happening. In a couple of cases, managers have walked up to me during the first round and said, “Look at how focused each of the teams is! And notice how quiet it is in here! Everyone is working so hard! This is great!” One of the managers was kidding: she knew that the lack of communication would be a problem. But the other manager? She was not kidding. She was dead serious. That’s what she thought productive teams looked like.

As you can probably imagine, I have lots of stories about this simulation. There’s the story of the Hero who single-handedly almost caused the failure of the whole company. There’s the story of the group that actually did fail entirely, and then blamed me for their failure, as though I had played some trick on them. There’s the story of the Micromanaging Manager. There’s a story about a Project Manager who quit in disgust after 15 minutes. And there’s a story about a Product Manager Who Always Said No.

There are stories about Developers arguing with the Computer about the correct interpretation of the code. And there are numerous stories of Product Managers who got so wrapped up writing requirements they forgot to talk to the customer, and Developers who wrote Code that was so complex even they had no idea how to interpret it, and Testers who spent so much time documenting test cases that they forgot to execute them, and myriad other forms of organizational dysfunction that just happen to look a whole lot like real life. That’s why simulations are so much fun: they give us the opportunity to experience all the complexities of the real world distilled into a microcosm.

Along the way I’ve learned numerous lessons like “Never Use a Communication Solution to Solve a Visibility Problem,” and “When Someone Says They Want Control, They Might Just Need Visibility,” and “If the Customer Offers You an Example, Take It.” So I’ll tell stories about those lessons too.

But all those stories will have to wait for another day. This entry is long enough as it is.

by Elisabeth Hendrickson at November 14, 2008 01:20 AM

November 13, 2008

Eric Jacobson

Use Your Brains, Not Your Requirements

Many of my notes from Hans Buwalda’s STPCon session are test design tips that can also apply to manual testing. One of my favorite tips was to remember to go beyond requirement-based testing. A good QA Manager should say “I know you have tested these ten requirements, now write me some tests that will break them”.

As testers, we should figure out what everyone else forgot about. These are the good tests. These are where we can shine and provide extra value to the team. One way to do this is to take a simple test and make it more aggressive.

Example Requirement: A user can edit ItemA.

Requirement-based Test: UserA opens ItemA in edit mode.

How can I make this test more aggressive? Let’s see what happens if:

  • UserA and UserB both open ItemA in edit mode at the same time.
  • UserA opens ItemA in edit mode when UserA already has ItemA in edit mode.
  • UserA opens ItemA in edit mode, makes changes, goes home for the weekend, then attempts to save changes to ItemA on Monday.
  • UserA opens ItemA in edit mode, loses network connectivity, then attempts to save ItemA.

What else can you think of?

by noreply@blogger.com (Eric Jacobson) at November 13, 2008 08:04 PM

Sebastian Bergmann

Test Dependencies in PHPUnit 3.4

Back in July, I came across an academic paper (more academic papers on testing that I read recently) titled "JExample: Exploiting Dependencies Between Tests to Improve Defect Localization".

"A well-designed test suite should exhibit high coverage to improve our chances of identifying any defects. When tests fail, we want to quickly localize defects, so we want our attention to be focussed on the relevant failing tests to identify the root cause of the defect. However, when some part of the base-code gets changed, a small defect can cause a domino effect of multiple failing unit tests. This is a problem, because the person changing the code has no other option than to browse all failing unit tests to try and deduce a single root cause. This task can prove to be quite difficult when that person is unfamiliar with the test code that fails."

For the upcoming PHPUnit 3.4 I have implemented support for the idea expressed in the paper mentioned above.

Let us have a look at the following code:

<?php
class DependencyFailureTest extends PHPUnit_Framework_TestCase
{
    public function testOne()
    {
        $this->fail();
    }
 
    /**
     * @depends testOne
     */
    public function testTwo()
    {
    }
}
?>

When we run the test above, the execution of the second test will be skipped as the test it depends on (testOne() did not pass:

sb@ubuntu ~ % phpunit --verbose DependencyFailureTest
PHPUnit 3.4.0-dev by Sebastian Bergmann.

DependencyFailureTest
FS

Time: 0 seconds

There was 1 failure:

1) testOne(DependencyFailureTest)
Failed asserting that <boolean:false> is true.
/home/sb/DependencyFailureTest.php:6

There was 1 skipped test:

1) testTwo(DependencyFailureTest)
This test depends on "DependencyFailureTest::testOne" to pass.

FAILURES!
Tests: 2, Assertions: 0, Failures: 1, Skipped: 1.

Some details about this new feature:

  • A test may have more than one @depends annotation.
  • @depends method references the test implemented in method() of the same class.
  • @depends class::method references the test implemented in class::method().
  • PHPUnit does not change the order in which tests are executed, you have to ensure that the dependencies of a test can actually be met before the test is run.

Please play with this new feature and provide feedback about its usefulness and usability.

by nospam@example.com (Sebastian Bergmann) at November 13, 2008 07:10 PM

Google Testing Blog

TotT: Finding Data Races in C++

If you've got some multi-threaded code, you may have data races in it. Data races are hard to find and reproduce – usually they will not occur in testing but will fire once a month in production.

For example, you ask each of your two interns to bring you a bottle of beer. This will usually result in your getting two bottles (perhaps empty), but in a rare situation that the interns collide near the fridge, you may get fewer bottles.

 4 int bottles_of_beer = 0;
 5 void Intern1() { bottles_of_beer++; } // Intern1 forgot to use Mutex.
 6 void Intern2() { bottles_of_beer++; } // Intern2 copied from Intern1.
 7 int main() {
 8 // Folks, bring me one bottle of beer each, please.
 9 ClosureThread intern1(NewPermanentCallback(Intern1)),
10 intern2(NewPermanentCallback(Intern2));
11 intern1.SetJoinable(true); intern2.SetJoinable(true);
12 intern1.Start(); intern2.Start();
13 intern1.Join(); intern2.Join();
14 CHECK_EQ(2, bottles_of_beer) "Who didn't bring me my beer!?";
15 }



Want to find data races in your code? Run your program under Helgrind!

$ helgrind path/to/your/program
Possible data race during read of size 4 at 0x5429C8
at 0x400523: Intern2() tott.cc:6

  by 0x400913: _FunctionResultCallback_0_0::Run() ...
  by 0x4026BB: ClosureThread::Run() ...
  ...
  Location 0x5429C8 has never been protected by any lock
  Location 0x5429C8 is 0 bytes inside global var "bottles_of_beer"
  declared at tott.cc:4



Helgrind will also detect deadlocks for you.

Helgrind is a tool based on Valgrind. Valgrind is a binary translation framework which has other useful tools such as a memory debugger and a cache simulator. Related TotT episodes will follow.

No beer was wasted in the making of this TotT.

Remember to download this episode of Testing on the Toilet and post it in your office.

by dastels (noreply@blogger.com) at November 13, 2008 10:44 AM

Michael Bolton

Heuristics Art Show, EuroSTAR 2008

Galvanized by Jerry Weinberg's workshop on experiential learning at AYE 2008, I led a tutorial at EuroSTAR 2008 that included an experiential exercise invented by my colleague James Bach. I call it The Heuristics Art Show.

In small groups, people contributed, discussed, and refined headlines and descriptions of some of their heuristics, mostly to do with testing, but also to do with other aspects of life and software development. It was wonderful to tap the collective wisdom and experience in the room, and I think the results were marvelous. Many thanks to all who contributed to the exercise.

The pictures are up there in high-res form. Some of them are a little blurry, but they're all readable if you download the high-res version. One fine day I hope to transcribe them—or maybe a Kindly Contributor could do it.

The Art Show approach reminds me of the positive deviance initiative—a from-the-bottom-up, practice-based approach to process improvement. Wanna get better results in a hurry? Don't bring in the massive, unreadable tomes of "maturity" models; have real people, doing real jobs, share their practices with each other. The PD Web site has a great example; follow the link and check out the description and video of the Palmer Technique.

This kind of exercise will happen again at future conferences, to be sure!

http://www.flickr.com/photos/23076491@N02/sets/72157608997920373

by Michael (noreply@blogger.com) at November 13, 2008 04:45 AM

November 12, 2008

Ricardo Signes

astounding optimization! thanks nytprof!

We've been unhappy with the performance of some code, recently. I was pretty sure I knew where the problem was, but I thought I'd run NYTProf just to see how things looked. I'm running an older NYTprof, so it's not 100% clear that my SQL-level optimization is what I need to do -- but it's the right thing to do anyway. Anyway, I figured I might see something sort of interesting, but I never expected this:

Calls     InclTime   ExclTime     Subroutine
27,908        406        406     DBI::st::execute
543,412         79         31     Carp::caller_info

...and let's not go any further. The program took almost exactly 600s to run. Of that, nearly five percent was because the program called Carp, and it called it a half million times! What?!

I won't be coy, because I'm writing this while waiting for a test suite to run and while watching House. It turns out that it was related to this line:

Calls     InclTime   ExclTime     Subroutine
139,340        222          6     SUPER::get_all_parents

That subroutine looks like this:

sub get_all_parents {
  my ($invocant, $class) = @_;

  my @parents = eval { $invocant->__get_parents() };

  unless ( @parents ) {
    no strict 'refs';
    @parents = @{ $class . '::ISA' };
  }

  return 'UNIVERSAL' unless @parents;
  return @parents, map { get_all_parents( $_, $_ ) } @parents;
}

See how it calls $invocant->__get_parents? Well, that's great, except that our internal ORM has an AUTOLOAD subroutine that looks like this:

sub AUTOLOAD {
  my $self = $_[0];
  my $class = (ref $self) || $self;
  (my $method = $AUTOLOAD) =~ s/.*:://;
  return if $method eq "DESTROY";
  unless (blessed($self)) {
    confess qq(AUTOLOAD: \$self for ->$method is not a blessed reference: )
      . Dumper($self);
  }

  ...
}

Now, to avoid hitting the database too much, we have a mixin that makes it talk to a memcached. That mixin (like many such modules) uses SUPER.pm. SUPER then calls __get_parents on our ORM, but hits the AUTOLOAD instead, and since that's only supposed to work on objects, it confesses. It does this every time we check consider using a cached copy of an object, causing us to invoke Carp::confess a half million times.

The solution? I added this line to our ORM:

sub __get_parents { return; }

Shaved two minutes off the test case. That's about 20%.

by rjbs at November 12, 2008 02:33 AM

November 11, 2008

Bret Pettichord

Watir Released with Improved Support for Firefox

Last week we released Watir 1.6.2. This is a big release with a lot of new features and fixes, but the focus has been integrating the Watir and FireWatir code bases and improving our support for Firefox. Earlier this year we put both projects under the same umbrella. This release significantly improves compatibility. Many of our users are finding that they can now run all or nearly all of their tests on both IE and Firefox.

We've also provided other features and fixes that will be of interest to users who don't care about Firefox (if such people exist). It is backwards compatabible, so we expect all Watir users will be upgrading to this release. Install or upgrade to this release.

And the end of this note, we mention a few issues that people have encountered when upgrading to this version.

Firefox Support

We've fixed many of the reported compatibility issues. FireWatir now supports nearly all off of the elements supported by Watir. Also both implementations now support being able to specify page elements using multiple attributes (e.g. browser.button(:name => 'Purchase", :index => 2).click). Lots of other issues, detailed in the release notes, have also been fixed.

Both Watir and FireWatir users can simply upgrade and continue to run their existing tests. But they can also make use of our new generic browser interface.

require 'watir'
browser = Watir::Browser.new
Once you have changed your tests to use this instead of Watir::IE.new, then you can configure which browser will be used at runtime.

Modal Dialog Support

We have updated Watir's modal dialog support to work with Ruby 1.8.6. Previously, users who needed to work with the showModalDialog had to use Ruby 1.8.2, but this restriction is no longer in place. We now recommend that all Watir users use the latest version of Ruby 1.8.6.

Speed Improvements on IE

We made some speed improvements in early version of Watir 1.5 that stopped working with version 1.5.4 - 1.5.6. These speed improvements are now working again. Users who had not upgraded to 1.5.6 because of performance concerns should upgrade to this release of Watir.

We've also added unit tests that will alert us if we happen to break this functionality in the future. Sorry about that.

Multiple Attribute Support for All Page Elements

I mentioned this above, but it bears repeating. Previously, Watir allowed you to access some page elements using multiple attributes, but you could only use a single attribute to access input elements such as buttons or text fields or select lists. Now you can use multiple attributes to access any of these elements. There is no limit to the number of attributes you can use. In other words, multiple attribute support has been improved for both IE and Firefox

Don't use "include Watir" at Toplevel

For some time, we've been telling people to avoid using "include Watir" in their scripts because it had the potential to cause unforeseeable problems. With this release, it causes conflicts with one of the other libraries that Watir uses. If you have been using "include Watir" in your scripts please rea