No Steps to Faster Testing

Posted by Doug Mon, 10 Oct 2005 03:30:48 GMT

I was actually hoping to title this blog post “Five Easy Steps to Faster Testing.” Unfortunately not. Here’s why I’m complaining about testing performance:

$ time rake
blah blah blah blah blah
Started
.................
Finished in 81.306421 seconds.

115 tests, 353 assertions, 0 failures, 0 errors
blah blah blah blah blah blah
Started
.......................
Finished in 85.885546 seconds.

89 tests, 703 assertions, 0 failures, 0 errors

real    3m5.970s
user    1m48.390s
sys     0m8.410s

Ugh. It get’s really, really annoying to have to do that a few times in an evening.

So, I had heard that SQLite was really, really fast. I thought that most of my bottle neck in testing is loading and unloading the database. I’m still using MySQL with old MyISAM files; so not transactions for me. The directions on How to use SQLite in Ruby on Rails seemed so clear, I was sure I could get it working in no time.

My plan was to leave MySQL as my development and production databases, but switch to SQLite for testing. The first problem turned out to be what I’m calling a bug in DarwinPorts portfile for SQLite. It appears that swig must be installed before you install SQLite, but it’s not a dependency. So, install swig via ports, sqlite3 via ports, and sqlite3-ruby via gems. OK, I’m working.

Second problem: rake wants to just dump the structure from development and then load that into testing. But the schema from MySQL isn’t compatible with SQLite. OK, I modify the Rakefile to not do that.

So now I’m running my tests. Keep in mind all my tests pass with MySQL. The first thing I note is that my tests don’t seem to be running that much faster. Then I see a test fail. Then things get really slow; no wait, it’s hung. The thing is I have no idea why my test failed and then another one hung. By this point I had sunk more time into it than I had to spare. I decided to punt.

I don’t mean to trash-talk SQLite. I’m sure it’s a marvelous database and I’m the screwup for not being able to get it to work smoothly. But, I did loose probably four or five hours to this experiment. I had to write something to account for my time.

Posted in ,  | Tags , ,  | 1 comment

Calendars and Group Scheduling

Posted by Doug Sat, 17 Sep 2005 06:05:04 GMT

It’s been a pretty good couple of days for Rails coding. I’ve done a bunch of validation tweaks, mostly finished the calendar, and begun on group scheduling.

I was having problems using embedded hidden forms for all my edit and add links on events. I did a couple things to improve the performance of the page. First, I ditched the embedded forms and made them separate page loads. It was cool to have the embedded forms the magically appear and disappear; I miss it. Several people suggested I just embed a single edit form and a single add form and use Javascript to update the values before it’s submitted. If I were a Javascript stud that’s what I’d do. Maybe when I’m all grown up I’ll be smart enough to do that.

The other thing I did was change how I tested for events on calendar days. I had a find_by_day method that would basically find(:all).select { |expr| expr.occurs_on?(day) }. I’d then loop over the calendar days calling that function. What I decided to do instead was simply collect all the TimeExpressions into a single list in the controller and let the view do the select for each day. This exposes more of the model’s logic a little. I like the way the code looks to simply calll find_by_day for each day. However, only doing one find and then doing the selects in the view shaved a fair amount of time off the page load.

So I’m doing some “group scheduling” too. It’s quite limited. The TimeExpressions I’ve been working with is really to build a “free-busy” schedule of available times to book appointments. What I need to do is allow a user to invite another user to an appointment. These two users may have to negotiate an appointment time. So, it makes sense for my Invitations to acts_as_versioned. I had seen acts_as_versioned discussed a couple times on the maling list. Let me just say, I’m really happy with it. I was able to set it up without too much fuss. It works pretty much exactly as advertised. Thanks technoweenie!

Finally, to send out the initial invitations I finally got around to coding some AJAX stuff. It’s quite simple; just a link that makes a single request to send the invitation. I felt so sophisticated! Only about an hour or so to get it studied, written, tested and committed.

Posted in ,  | Tags , , ,  | no comments

More Calendar Fun

Posted by Doug Tue, 13 Sep 2005 17:15:22 GMT

So I had what I thought was a pretty workable calendar component ready for my client. Once she had a look at it, she didn’t like it. Turns out she’s a more “visual” person. That means she wants to see the calendar events on the day they occur inside the calendar. What I had given her was pretty much just a daily view using jscalendar as the main navigation to change days.

Before I go on, I’d like to thank Jim Weirich for pointing out Runt, which is a temporal expression library. It’s basically exactly what I was working towards with my TimeX class. I haven’t switched to using runt just because what I have works so far. I may still switch in the future. I know I have other stuff that can use that logic. I’m just not sure about rewriting what I already have at this point.

As it turns out though, building my own monthy calendar grid was fairly simple. So simple, I’ll go ahead and include the code for it here:

  def calendar_grid(year, month)
    # We're going to build a 5x7 grid of calendar dates
    first_day = Date.new(year.to_i, month.to_i, 1)
    # finding the last day of the month is a little clumsy
    last_day = (month == 12) ? Date.new(year + 1, 1,1) - 1 : 
       Date.new(year,month + 1, 1) - 1
    grid = Array.new
    week = 0
    # start on the beginning of the week of the first of the month
    current_day = first_day - first_day.wday
    while current_day <= last_day
      grid[week] = Array.new
      0.upto(6) do |wday| 
        grid[week] << current_day
        current_day = current_day + 1
      end
      week = week + 1
    end
    return grid
  end

Just displaying the grid is also only about 10 lines of RHTML. I then went on to include the events on each day and add links for managing those events. Boy did the page get heavy fast!

I was happy with the quick-post logic for adding new categories in typo. I wanted to use that for adding an appointment for each day. I already had that logic for my previous daily view, and only had to do minor changes to put the Effect.BlindUp form on every day in the calendar.

The new event form is a little large. It’s got two select boxes with all the time increments from 7am to 10pm in 15 minute steps. Adding a “new event” link to every day in the 5×7 grid put a lot of weight on the page. Don’t forget that for every day in the grid I have a pretty crude find_by_date method to scan the TimeExpression table filtering out any that don’t occur on the day in question.

The page isn’t too bad. Even running on webrick in development mode, it loads in a few seconds. Hmm, here’s all these events listed. I need to edit them. OK, I’ll just adapt the quick-post forms for adding a new event to edit the listed event. For an even that repeats three times a week, that’s 15 more somewhat large forms that are embedded and hidden on the page. Plus, more logic to evaluate the event object to build the form.

So, with just a few events I’ve got like 50 copies of essentially the same form. That’s a lot of duplication! The page can easily come in at over 200K. That’s a lot to download and a lot to generate with ERB. I’m not sure what to do about it though short of not embedding all those forms. If I had to reload a new page for each of those “edit” and “add” links rather than embed the form, the whole app may actually be faster. I’d lose a little cool factor of using the Effect.BlindUp; but I’m not so sure my client cares about that.

While I’m at it, I still haven’t gotten the sophisticated “delete” operation done. I can delete a whole event; but I can’t do nice things like “delete only this one occurance of the event” or “delete all future events”. The controller logic is simple. The model already supports it. To keep the UI consistent with what I’m doing now though I’d have to embed another form for every event with the radio buttons for the choices.

I’ll get this worked out today. I’ve got another demo tonight with the client.

Posted in ,  | Tags ,  | 5 comments

Older posts: 1 2 3 4

Copyright 2001 - 2005 by Lathi.net and Doug Alcorn

Creative Commons, Some Rights Reserved Ruby on Rails Developer Powered by Debian GNU/Linux Powered by Typo