Showing posts with label seneca. Show all posts
Showing posts with label seneca. Show all posts

Wednesday, February 28, 2007

CSS Notebook Layout

Ever wanted a notebook style layout on a web page?



Well, I sure did. And I spent the better portion of the day fighting with it making it work right. You can find a small example page here.

Here are the important parts of the CSS and Javascript:

For the 'tabs':

.tab {
border-top: 1px solid black;
border-left: 1px solid black;
border-bottom: 1px solid black;
padding-top: 5px;
padding-bottom: 5px;
padding-left: 15px;
padding-right: 15px;
vertical-align: middle;
text-align: left;
color: blue;
cursor: pointer;
}


Each tab also has it's initial 'background-color' set.

Here is the corresponding HTML:

<div>
<span id="page1Tab" class="tab" onclick="showPage('page1');">
Page 1
</span>
<span id="page2Tab" class="tab" onclick="showPage('page2');">
Page 2
</span>
<span id="page3Tab" class="tab" onclick="showPage('page3');" style="border-right: 1px solid black">
Page 3
</span>
</div>


It's important to note that for the frame to properly line up with the bottom of the buttons that it needs to have it's 'margin-top' identical to the tabs 'padding-bottom'. This is what my "content" frame looks like:

div#content {
width: 95%;
border: 1px solid black;
margin-top: 5px;
background-color: #B5BBD5;
}


I'm using <fieldset> tags with <legend> tags in my example to get the neat looking frame.

Finally, here are links to the HTML, CSS, and Javascript files:

Thursday, November 30, 2006

Edgy Eft

Today I set out to install the latest version of Ubuntu, Edgy Eft (6.10). I've been an Ubuntu user since Warty Warthog (4.10) and a long time Debian user before that. I'm continually impressed with how they take the Debian base and polish it so well. I've always told people that Ubuntu "is like Debian with a better package set".

Since Dapper Drake (6.04) Ubuntu has had a new installer. It is more or less just an application that runs inside of a Live CD. The organization and feel of it is very similar to it's text based counterpart. I'm all in favor of a GUI installer but very disappointed with Ubuntu's. This post will detail the downfalls of it.

For the record, here is a summary of the hardware I was installing on:

  • IBM Thinkpad R51

  • 512MB PC2700 RAM

  • Intel Pentium M 1.5GHz CPU

  • Intel Pro Wireless 2200 a/b/g

  • CD-RW/DVD-ROM

  • 40GB Hard Drive

Monday, November 06, 2006

FSOSS 2006 -- Now with more freedom!

I've just finished converting all of the video and audio from the Seneca Free Software and Open Source Symposium to Ogg Theora and Ogg Vorbis respectively. They are in the process of being mirrored right now. Check this page in a day or two to download them.

Friday, November 03, 2006

More Unit Testing


bhearsum@wesley:~/projects/mozilla/buildbot/buildbot-bonsai/buildbot/test$ trial test_bonsaipoller.py

Ran 9 tests in 0.061s

PASSED (successes=9)


So I've finished my first set of test cases, rejoice!

When I started writing them I thought it would be really easy, I didn't expect to spend more than a few hours on them. Boy, was I wrong. It's been over a week since I started and I probably spent 8 to 10 hours total on a 181 line file. I received help and advice along the way from Rob Helmer for which I am much appreciative.

Problems I encountered

  • My original code was more or less untestable

  • Python regular expressions were confusing

  • My original code used a mixture of exception and return values for error reporting

  • Comparing two objects by their data, _not_ their references



Very quickly I decided to do rewrite of the BonsaiPoller module. It was untestable, confusing, and just plain ugly. I had been planning to do a rewrite becausue of the ugliness alone, so it wasn't hard to reach this decision. This also gave me a chance to attempt some test-driven development. I was looking at _some_ of the old code while writing the test cases but by the end the BonsaiPoller and BonsaiParser worked quite a little differently internally. For reasons of simplicity I decided to keep the interface the same.

I found much of the test case writing very tedious. Just inputing all the data I needed was a chore. I thought it might be easier to input one "good" piece of data and base all of the broken ones off of it. This worked well enough while using the replace() method to do simple substituition but as soon as I needed regular expressions I was in a world of hurt. For some reason the Python developers seem to have decided that they don't want regular expressions as a built-in part of the language. For the life of me I don't know why. I was stuck carrying around a 're' (regular expression) object for most of the regular expressions I used. Compared to how they work in Perl it's a complete pain in the ass. Observe:
Python:

import re

data = "<blah><ci><f></f></ci></blah>"
myre = re.compile("<ci.*></ci.*>", re.DOTALL, re.MULTILINE)
newdata = re.sub(myre, "", data)

Perl:

$data = "<blah><ci><f></f></ci></blah>"
($newdata = $data) =~ s/<ci.*><\/ci>//;


Not such a big deal when doing one or two, like I was, but if you're doing heavy text parsing this would be an ugly nighmare.

In my original code I used a lot of 'return True' and 'return False' to indicate when there was no more data. Seeing as python is object oriented and throws lots of exceptions I wanted to be consistent. This made much of my code a _lot_ cleaner and it has a nicer "feel" to it. There's one part I'm still not happy with though.
Here's the code when I was using True/False:

data = BonsaiResult()
while self._nextCiNode():
ci = CiNode()
ci.log = self._getLog()
ci.who = self._getWho()
ci.date = self._getDate()
while self._nextFileNode():
fn = FileNode()
fn.revision = self._getRevision()
fn.filename = self._getFilename()
ci.files.append(fn)

data.nodes.append(ci)

return data

And with exceptions:

nodes = []
try:
while self._nextCiNode():
files = []
try:
while self._nextFileNode():
files.append(FileNode(self._getRevision(),
self._getFilename()))
except NoMoreFileNodes:
pass
except InvalidResultError:
raise
nodes.append(CiNode(self._getLog(), self._getWho(),
self._getDate(), files))

except NoMoreCiNodes:
pass
except InvalidResultError, EmptyResult:
raise

return BonsaiResult(nodes)


I tried to think of a way to use exceptions cleanly with while loops but drew blanks. If anyone can think of a way to improve the above code please let me know! The function works fine, however, so I shouldn't worry so much.

The last problem I ran into was comparison of my BonsaiResult objects. I didn't have this problem before writing the test cases because there was no point where I needed to compare them! This part wasn't too difficult once I figured out what I had to do -- but that took awhile. I was considering pulling the __cmp__() method before creating a diff but I don't think it hurts to leave it in.

Overall I am very pleased with my test cases and new BonsaiPoller module. As soon as I get the energy I will be submitting it to Brian.

Saturday, October 28, 2006

Firefox Party - A Smashing Success

As part of Club Moz at Seneca I was involved with running our Firefox 2.0 Launch Party after the FSOSS last night. After some bribery with stickers and t-shirts (thanks Asa!) and the promises of pop and chips we managed to drag quite a few people in. There was music, chit-chat, and some pictures taken. El Presidente, gave a quick speech thanking everyone for showing up. Given the short amount of time we had to plan this event I think it went very well. There's a lot we can do to make the next ones better and I've gotten some ideas from reading other blogs. So, you ain't seen nothing yet!

So thanks to everyone that helped out: Tom, Liz, Vanessa, Phil, Moe, Dave, Asa, Andrei, Seneca Student Federation, and of course John, for giving us the Club Moz idea in the first place.

Thank you to Mike Shaver and David Humphrey for telling me what a success the party was -- it was good to hear someone else thought so!

Thursday, October 12, 2006

The little connection that couldn't.

The wireless internet at my school sucks. Since the start of the Fall semester is has been barely usable. My connection is dropped every 2 to 10 minutes. I've upgraded the drivers for my wireless card -- didn't help at all. It happens all over the damn school but not *all* the time.

It's hard to say exactly what it is. Between the summer and fall semesters I upgraded to Ubuntu Dapper, but I don't think that would cause these problems. Especially since I'm running a custom kernel and the latest drivers. Tom has similar issues. I think it's just the access points being overloaded with traffic.

It's really frustrating though, and defeats the purpose of having wireless access.

New Buildbot Patch

I've submitted my latest patch for the Buildbot. This one adds support for per-build comments akin to the Tinderbox feature.

This patch was a lot tougher than the previous ones. I went through implementation of a couple different ideas before I found a way that worked and wasn't an ugly hack. Right before creating the final diff I ended up not including my "user javascript" support. When I look at the patch now it has absolutely no code from my first attempt in it. I've read that this is often the case but I've never experienced it until now. Working on the Buildbot has really proved to me the need for some design before implementation. During my first two revisions of this patch I *did* do some design but I skimped out after getting the general idea and ended up tossing all of that code out.

Working with C++ for the past 8 months really turned me off of OOP, or so I thought. Working with the Buildbot has been a good experience for me. It's a mid-sized project, very highly designed, and very well implemented (at least from what I can tell). It has shown me that OOP doesn't have to suck, and that not all OOP languages suck.

Friday, October 06, 2006

On unit testing

I've been hacking on the Buildbot for a month or so now. I've released two patches for it, a Bonsai Poller and a Tinderbox Mail Notifier. I noticed recently that Buildbot has a lot of test cases in it's tree. I've heard the phrases "unit test" and "test case" before but I didn't know what they were until today. My patches are more or less complete and have been tested but I still think it would be nice to have test cases for them. The buildbot tree will change, bonsai and tinderbox may change, and this should be a relatively simple way to get me introduced to the concept of unit testing.

I spent an hour this afternoon reading Buildbot test cases and other unit testing documents. The Buildbot uses Twisted's unit testing framework for it's tests. I found the docs for those here. This went into the specifics of writing test cases with Twisted but after reading it I still didn't feel comfortable with the concept. There was a link to Dive Into Python on the Twisted page. This is an excellent read for anyone new to unit testing. It goes from no source to test case to working code.

I've done much of what is involved in making a test case without actually making a test case. One of the key things I like about unit testing is that it defines your API. I was chatting about this in #seneca and shaver said "that also has the nice effect of keeping you honest about what you really _need_". This is a very good thing for someone like me! I went through 3 or 4 revisions of my BonsaiPoller classes before coming to the final version. I don't think this is necessarily a bad thing but I know this happened because I didn't think enough about what it should look like before attempting to implement it. Before writing the final revision I actually wrote a script that defined how I was going to use the class. Looking back on it, that was a rudimentary test case. It wasn't well organized, it wasn't testing small pieces at a time, but from a design standpoint it accomplished the same thing.

I see lots of similarities to unit testing and things I've encountered in my classes. We often get "test mains" from professors to test our assignments before handing them in. These are often in the form of small tests to every part of our classes. In my systems course we just finished doing Scenarios. To me, a scenario seems like a test case for use case description. There is obvious differences but while a test case tests the validity of code, a scenario tests the validity of a use case description.

Unit testing is very interesting! I plan to adopt it whenever I can. I expect that I will go from idea to working code quicker if I do it right.