A lot of things got done since the last time I blogged. I probably should've blogged about them as they happened, but instead I think I'll roll them all up into this one.
Using Git and GitHub
I've been using Subversion for a long time. When I took ICS 413 in fall of 07, we used Subversion and Google Code to host our assignments and projects. When I had my research assistantship in LILT, we used Subversion to host all of our Ruby code. So I have more than a passing familiarity with Subversion, although I never really got into the ins and outs of branching and merging.
But it's hard to get away from the Git hype. I spoke to a colleague (the former LILT release engineer) and he was very hyped about Git and how Heroku uses it for deploying Rails projects. We briefly covered Git in our software engineering class last fall, but we still used Subversion. So I jumped at the opportunity to get familiar with it more, and I'm enjoying it. I created a branch called "release" that will only hold stable versions of my code while I work off of master. I did this in part because I want other developers to start working on a stable version rather than my working branch because many things could change. Since I'm on a 2 week milestone schedule, I'll be updating the release branch fairly regularly.
The network graph of my GitHub repository.
In addition to the release branch, I'm tagging the release branch with milestone markers. It's neat how GitHub resolves these tags into downloadable packages of the source code. The very act of tagging and pushing the tag onto GitHub made a downloadable distribution available. I wish I had known that sooner so that I could use a different commit message.
Downloads for the project.
So I'm pretty psyched about using Git now too. It'll be interesting to see what happens when the other collaborators come on. I'm encouraging them to work on a separate branch so that they don't get all of the small changes that I push onto GitHub. The database models can change and that would require the other collaborators to blow away their database and rebuild it (since Django doesn't have migrations without the south app). This way, I can merge in my stable versions and have collaborators work off of those.
Selenium was one of the most awesome testing tools I've used. We use it on a Rails project that I work on. However, integrating it with Django seems to be tricky. There are people working on it, but there doesn't appear to be a perfect solution. However, people have also mentioned another testing framework called Windmill that has better Django integration. So I thought I'd check it out and see if I can get it working with our project.
Running a Windmill test.
The results are mostly satisfying. I created a basic test using the IDE that browses through the tabs and checks a few items. I copied the resulting Python code and added it to my project. After writing a short script to check if Windmill is installed and to prepare it for Django, I have it running as part of my unit tests. The only downer is that it seems to throw errors on our continuous integration server. It's something that I should probably fix because integrating Windmill with Hudson would be an important step as far as making sure everything's working properly.
# Generated by the windmill services transformer
from windmill.authoring import WindmillTestClient
client = WindmillTestClient(__name__)
client.waits.forElement(link=u'Energy Hub', timeout=u'8000')
client.asserts.assertText(xpath=u"//div[@id='content']/div/div/h3", validator=u'About the Kukui Cup Competition')
The actual Python script that Windmill is running.
Most of the work I've done thus far is creating content. I haven't done any real Python programming except for my testing scripts. But as I implement the features, I'm learning more and more about Django and Python. I still think of myself as a beginner, but I'm learning a lot about the framework and the language. Over the past few days, I implemented activities and commitments on our profile page. During the process, I learned about generator expressions, properties, and how the model filter/exclude methods work. I used abstract models since many properties of activities, commitments, and goals are similar. I even brushed up on regular expressions by creating urls that dynamically call functions. Instead of a "add_activity" and "add_commitment" url entry, I have a regular expression that's basically "add_(commitment|activity)" that calls a view method called "add_membership". "add_membership" takes the object type (commitment or activity) as a parameter and calls the necessary method.
Current user profile with commitments and activities.
I'm enjoying working on the project more and more. I'm excited to see what I'll learn next.