Loading ...
Sorry, an error occurred while loading the content.

Statefulness, premature optimizations, and changes to client_redirect

Expand Messages
  • Rob Nagler
    We ran across a problem today with an acceptance test. The code looked roughly like: test_setup( BlaProject ); follow_link( Reports ); foreach my $year
    Message 1 of 1 , Jan 23, 2004
    • 0 Attachment
      We ran across a problem today with an acceptance test. The code
      looked roughly like:

      test_setup('BlaProject');
      follow_link('Reports');
      foreach my $year (2003..2004) {
      submit_form(OK => {
      Year => $year,
      });
      my($reports_page) = get_uri();
      foreach my $link (qw(
      Report1
      Report2
      Report3
      )) {
      follow_link($link);
      verify_uri(qr/$year/);
      verify_text($year);
      visit_uri($reports_page);
      }
      }

      The test would fail on the second iteration at verify_uri(). Because
      there was a recent change to verify_uri(), we thought the bug was
      there. We focused all of our energy in that code. Of course, the
      problem was related to the $reports_page variable.

      Here we were trying to "stake down" the code with a variable, when the
      simpler, less stateful code, and correct code is:

      test_setup('BlaProject');
      foreach my $year (2003..2004) {
      foreach my $link (qw(
      Report1
      Report2
      Report3
      )) {
      follow_link('Reports');
      submit_form(OK => {
      Year => $year,
      });
      follow_link($link);
      verify_uri(qr/$year/);
      verify_text($year);
      }
      }

      We were fooled by competing statefulness. The test object keeps the
      current URI, but it doesn't keep more than that. The uri returned
      after the form submission isn't actually the current year, because the
      form does a server redirect, not a client redirect. That shouldn't
      matter to the end user, because the browser would warn, "To view this
      page, you need to resubmit your data...".

      This is the nature of browsers, but it's an unnecessary complication
      for the test infrastructure. The stateless code is almost as
      efficient, but more imporantly is simpler. The two foreachs simply
      iterate the one case (all the stuff in the inner loop). This is a
      good way to think of acceptance tests with multiple data, such as this
      one.

      It's amazing after all these years of preaching the benefits of
      declarative programming, I still fall into simple traps like this.
      When writing imperative code, it's best to write it simply without
      temporary variables. The $reports_page was a premature optimization,
      which, of course, wasted a tremendous amount of development time where
      it would have saved a miniscule amount of time during *test*
      executions. Tests should run fast, but they should run correctly.
      The best way to ensure correctness is to avoid premature
      optimizations, i.e., unnecessary statefulness.

      The testing of this form is related to fixing some behavior in bOP,
      btw. Currently, bOP doesn't allow you to client_redirect to the same
      task. Bivio::Agent::HTTP::Request silently transforms such
      client_redirects into server_redirects. This is because certain
      browsers long ago would get confused if you redirected to the same URI
      even when the query string changed. Turbine (Jakarta project) had
      similar "protective" code, but they've since removed it. What's good
      enough for Java is good enough for us. ;-)

      Rob
    Your message has been successfully submitted and would be delivered to recipients shortly.