A complex, flexible table layout

Posted March 25th, 2009 by spanky. Comments Off.

Greetings!

I was given the task of building what appeared like a relatively simple table for work, but in the end it turned out to have quite a few challenges, and I figured I’d document how I did it in case someone else wanted to give it a try (or I had to do it again.) NOTE: I originally did this with DIV’s and reverted to a table, and some of the CSS was more important then. First, let me show you what I was given:

The Photoshop file

The Photoshop file

OK, so you can see at first glance it looks pretty simple. Here are some of the tricky parts:

  1. The height must be flexible, since different browsers will have different font sizes
  2. The cell borders must overlay the shaded border
  3. There is a slight gradation in the background of the table
  4. Table has no outside border

So, here’s how (I think) I did it.

First the entire table is wrapped in a div with id “#left” for positioning and isolation purposes. (The page had another smaller box floated right.) The #left div has a set width and a background image. The background image is sliver of the gradation and is set to repeat-x and to sit at the bottom:


#left {
width: 651px;
background: transparent url('/graphics/pricing-box-background.png') repeat-x bottom;
}

Next we define a table inside the DIV with the same width, no cellpadding, border, or cellspacing. Yes, I’m still old-school like that.

Here’s where it gets tricky. All the rows (TR) get a class of “row”, but the first and last row get ID’s of “first” and “last”. Each table cell (TD) gets a class of “column” and a class of “column-1″ or “column-2″‘ depending. (The first column has to be wider than the rest, but the rest have to be equal.) Here’s the HTML:

OK, now that might look simple, but the CSS is, well, involved. Let’s start with the “row” class:


.row {
width: auto;
margin: 0 auto;
background-color: transparent;
background-image: url('/graphics/pricing-box-border.png') repeat-y;
position: relative;
}

Things of note here: we style the row with a background PNG that is 651px wide and consists only of the shaded left and right border of the table, transparent everywhere else. This gets the edges of each row. Originally I had done this to the entire #left div, but for some reason I forget now, that didn’t end up working out, so I decided to do it to the row. IN the end I had to add “position: relative” to solve an IE 6/7 problem where background images applied to a row are inherited by the table cells contained in it. The other half of this hack is setting the TD’s to have no background image. See below.

Now to style each cell. I called them columns. Here’s the column CSS:


.column {
border-left: 1px solid;
border-top: 1px solid;
border-color: #ccc;
border-width: 1px;
background-color: transparent;
padding: 4px;
vertical-align: top;
background-image: none;
}

Things of note: the order I’ve defined the border widths and colors seemed important at the time but now I don’t see why. I do know that applying the border to the top rather than the bottom was significant because if you apply the border to the bottom, you have the problem where not all the cells are the same length…at least when they were DIV’s. It still seemed prudent to keep the borders on the top. I also put a border on the left, rather than the right because we have that second unique class on the first column (.column-1) where we can shut it off. The background-image: none is the second half of the IE6/7 hack where the cells inherit the background image of the containing row.


.column-1 {
width: 30%;
border-left: none;
padding-left: 12px;
}

Things of note: This column is wider than the others. I used percentages because I absolutely hate trying to calculate margin/padding/width nightmares. Give it a percentage, make them add up to less than 100% and most padding shouldn’t self-destruct the table. As you can see we turn off the left border in the first column to achieve the empty outside border of the table on the left side. I also want the text to have some breathing room, so I added a little left padding.


.column-2 {
width: 20%;
}

The rest of the columns are all the same width, adding up to 60%. Add 30% and you get 90%. This swallows up the remainder added by padding/margins, which are all calculated differently under different circumstances/browsers, so I just fudge it and come under. Note that because we chose to use the left border before, we don’t have to deal with shutting off the border on the right side. Easy.

Now we start to pile some things up using precedence.


#first .column {
border-top: none;
padding-top: 6px;
}
#first.row {
background: transparent url('/graphics/pricing-box-top.png') no-repeat top left;
}

Here we simply turn off the top border for the first row and give some breathing room to the titles. Also we add the shaded rounded PNG to the top row to round out the shaded border of the table. Note how the interior table border sits on top of this background image seamlessly. Nice.


#last .column {
border-bottom: none;
padding: 9px;
}
#last.row {
background: transparent url('/graphics/pricing-box-bottom.png') no-repeat bottom left;
}

Not much special here (and some unnecessary code, oops) to add the shaded border to the bottom. One thing of note here. Because the DIV (#left) has a gradation for a background, is positioned to the bottom, and sits UNDERNEATH the rounded corners, which are transparent, the gradation pokes through on the bottom corners. If you look carefully, I’ve added white to the corners to prevent this from happening.

Right now, this page can’t be viewed live, but when it’s live, I’ll post the URL in all its glory.

All in all, it’s way more work than it should be. Now that I look back, it’s way easier to explain than it was to do, simply because I tried a few things here and there. I might have to go through and lint pick the CSS for leftover stuff from when I was doing it with DIVs. I hope you liked this, if so, click my Google Ads a few times.

~Spanky

Plans:

Free

Unlimited

On-Demand

Customizing Selenium RC to take command line args

Posted December 30th, 2008 by spanky. Comments Off.

I’ve written a few lines of code that you can use to pass a URL or the browser type you want to use from the command line, using Python.  At the bottom of your Python-based selenium test, you can replace the “if __name__ ==” part with the following code:

if __name__ == "__main__":

    ### custom
    import sys, getopt
    global testurl, browser
    testurl = "http://127.0.0.1"
    browser = "*chrome"
    try:
        opts, args = getopt.getopt(sys.argv[1:], "", \
            ["url=","browser="])
        for opt, arg in opts:
            if opt in ("--url",):
                testurl = arg
                argument = opt + "=" + arg
                sys.argv.remove(argument)
            if opt in ("--browser",):
                browser = "*" + arg
                argument = opt + "=" + arg
                sys.argv.remove(argument)

    except:
        pass
    ### /custom

    unittest.main()

and the setUp method with:

    def setUp(self):
        self.verificationErrors = []
        self.selenium = selenium("localhost", 4444, \
            browser, testurl)
        self.selenium.start()

Then on the command line, you can go:

python test_myTest.py --url=http://myurl.com --browser=iexplore

I’m sure the code could be better, but I’m not that great with getopt.

~Spanky

Selenium RC, Firefox, and the Self-Signed SSL Cert

Posted December 30th, 2008 by spanky. Comments (9).

OK, this one’s been driving me nuts, mostly because it took the “automated” part out of automated testing, which basically defeats the purpose.  If I can’t run an automated test, I am much more prone to avoid running them, and therefore not test, and therefore introduce bugs.

The Problem:

The problem is with self-signed certs.  If you are working on something locally and it uses SSL (HTTPS), normally you’ll just create your own cert and forget about it.  The problem is that when you run Selenium RC (with Firefox/chrome) it’ll fire up a browser and when it reaches this secured page, it’ll throw an exception.  The exception is in an unscriptable window (AFAICT) and you wouldn’t want to code around the window in the test b/c it probably won’t happen on your staging or production servers.  Normally with Firefox, you can simply add an exception, which gets written to a file called ‘cert_overrides.txt’, and forever going forward you won’t need to worry about it.  Again, the problem is that because Selenium fires up a fresh profile each time you run it, you can’t simply add this exception anywhere.  You’d think adding the ‘-trustAllSSLCertificates’ flag to the command line when you start the Selenium Server would work, but it doesn’t.  I think the problem I’m having is not an expired or invalid cert, but that it’s self-signed and the CA is not trusted. (Whatever, all I know is that it doesn’t work).

The Answer:

Well, at first glance, it seemed like I could just make a blank Firefox profile, by firing it up from the command line and saving a new profile.  The problem with this is that the new profile won’t have all of the Selenium proxy stuff configured.  In fact, there’s seems to be a whole buncha stuff missing from the profiles, so I don’t recommend doing this.  If you really want to know how to create a blank Firefox profile.  Open a Terminal and type:

/Applications/Firefox.app/Contents/MacOS/firefox-bin -profilemanager

Once you’ve followed all the prompts, a new profile will be created in: ~/Library/Application Support/Firefox/Profiles

But anyhow, you want to know how to make it WORK not how it doesn’t work!  This is what I did and it seemed to work.  First create a Selenium test with one step that is basically a really long wait.  I use Python so I have this step in my test:

def test_WAIT(self):
    sel = self.selenium
    sel.open("/")
    sel.wait_for_pop_up('xxx', 999999)

This bascially gives you time to do the next step.  OK, so now in your Terminal, open the /tmp folder in a regular Finder window by typing: open /tmp – Now, fire up the Selenium Server, and run the test.  While the test is basically just hanging, you’ll see there’s a new folder in /tmp called something like: customProfileDir0ad7f0b886b7499bbf53d2ee5f4dc3dd. Drag this folder somewhere (like your Desktop), you should be asked to authenticate.  Once you’ve copied the folder to your desktop (or wherever), you can use it as an alternate profile for firing the Selenium Server.  I renamed the folder ‘SeleniumProfile’ and added the ‘cert_overrides.txt’ file to the folder (with the overridden cert information in it. If you override a cert in your normal profile, you can just copy it out of that file).  Now you can use this fully prepared and ready Firefox profile with Selenium Server by running:

java -jar selenium-server.jar -firefoxProfileTemplate ~/Desktop/SeleniumProfile

To me, this was the simplest path to getting going.

My suggestions:

If it were up to me, I woul ddo one of a few things:

  1. Make the -’trustAllSSLCertificates’ flag actually work.
  2. Make it such that when the Selenium Server fires up and copies the files out of the Firefox default profile (found in /Applications/Firefox.app/Contents/MacOS/defaults/profiles ), it should copy ALL of the files in that folder, rather than just localstore.rdf and a few others.  This way you could drop your cert_overrides.txt file in there and go on your way
  3. Include a fully formed “blank” profile with the distribution of Selenium RC to use or modify.

Other than that, I continue to use and love Selenium.  I hope this article helps and gives folks who are doing the development some ideas to make things better for the users.  I see a lot of these problems not properly answered in the forums and will be posting this blog link in there.

~Spanky

Mac OS X’s Ditto Command

Posted December 23rd, 2008 by spanky. Comments Off.

I learned of a new handy command while at the SF Apple Store getting my laptop fixed (long story).  Have you ever been copying a lot of files in the Finder, and left the room to make tea, watch a movie, or go to bed? (Yes, THAT much data?!) only to return and find that it crapped out part way through with some stupid File in Use or File Locked or other somesuch problem?  Well, I have.  Often.  This had led me in the past to do such large copies from the Terminal sudo-style.  When I was at the Apple Store, the “Genius” there told me about the command line tool called “ditto”.  The description from the man page reads:

In its first form, ditto copies one or more source files or directories to a destination directory.  If the destination directory does not exist it will be created before the first source is copied.  If the destination directory already exists then the source directories are merged with the previous contents of the destination.

Friggin’ awesome if you ask me.  This means when I’m recovering my hard drive to my (very stale) backup, I just use 'sudo ditto src dest' and it merges everything into one nightmarish glob that I’ll never look at again, but at least I know everything between the two is there.

I can also imagine it might be great for merging two iTunes Libraries.  Hope this is useful to you!

~Spanky

Building MySQL on Mac OS X Leopard

Posted December 18th, 2008 by spanky. Comments Off.

Hi and welcome back.  This blog is turning into Spanky’s Simple Steps for Starting Services!  See, I always spend all this time searching around for how to do things that I think should be really simple.  In the end, they usually are really simple, but nobody seems to document things in a way that makes sense, or the information is scattered all over the place and you have to piece it together.  Meh.  So, I hope you find these little tutorials helpful.

MySQL is Dolphin

MySQL is Dolphin

OK, so, MySQL is really easy to get running on OS X.  I’m using Leopard, but this should apply to any any version, AFAICT.  The first thing I tried was the binary installer.  I’m sure it works just fine, but when I tried to run it certain commands, I got errors so I wiped it and started from source.  I really prefer building things from source for understanding and control, although if I can have it done through a packaging system, I’m pretty happy with that too, because then you get updates and such free.  I’m sure I’ll write a post on Darwin Ports v MacPorts v source someday, but today is all about MySQL.

First, let me explain what my mission is.  I have to design a really simple database locally for a stop-gap application at work.  We’re migrating some other nightmarish MSSQL database to MySQL, but that could happen “any day” within the next 6 months.  I need to do this now.  So I’m going to build a super-simple database that I can connect to locally.  If you need a ‘real’ MySQL installation, like on a server, do not follow this guide.

Start by downloading the source. From this page click download the Community [Free] Server, and choose the ‘source’ option (all the way at the bottom).  I pick the Compressed GNU TAR archive (tar.gz) version.

Before I continue, I owe most of this to this article from Apple, which has lots of good background and explaination, but it was missing a thing or two.  I recommend reading it.  It’s the #1 Google response for “MySQL on Mac OS X”, but like I said, it’s missing a few key things.

I’m going to assume you downloaded the tarball to your Desktop, so all my paths are going to go from there.  Open a Terminal and type:

cd ~/Desktop
tar -zxvf mysql-5.1.30.tar.gz
cd mysql-5.1.30
./configure --prefix=/usr/local/mysql \
--with-unix-socket-path=/usr/local/mysql/run/mysql_socket\
--with-mysqld-user=mysql \
--with-comment --with-debug
make
sudo make install
cd /usr/local/mysql
sudo bin/mysql_install_db --force
sudo mkdir run
sudo chgrp -R mysql /usr/local/mysql

sudo chown -R mysql run
var
sudo bin/mysqld_safe --user=mysql &

OK, so now for the missing steps, you want to add the MySQL bin to your PATH, if oyu know how to do this already, go ahead, or type:

echo 'export PATH=/usr/local/mysql/bin:$PATH' >> ~/.bash_profile
source ~/.bash_profile

And finally you’ll want to secure everything.  This handy provided script does everything you need:

mysql_secure_installation

And seriously, that’s it.  Now you have a MySQL server installed.  To run it, just type:

sudo echo
sudo /usr/local/mysql/bin/mysqld_safe --user=mysql &

(If you don’t do the ‘sudo echo’ part first, and you’re not already sudo, you get this weird state where it wants you to type your password but it’s running in the background.)

And to stop it:

sudo mysqladmin -p -u root stop

I hope that this helps you get up and running quickly without having to piece together 5 different posts from forums and blogs.  If you like this article, click my ads!

~Spanky

Selenium RC

Posted December 15th, 2008 by spanky. Comments (2).

I hope you enjoyed Friday’s post on Getting Started with Selenium.  Today I spent some time messing about with Selenium RC, which I’d really like to use because it allows me to write the tests in Python.

My real need here is to add a smidge of programming to my test.  When I test our forms, I have to use a unique email address every time, otherwise we’ll cause an “address already in use” error.  I want to add a short random number to the email address to avoid this.  I would prefer to do this in Python although I know there are other ways.

Selenium RC uses a Java-based server to control your browser by setting up a proxy server running on port 4444.  When you run your test, it connects through this local proxy and drives your browser, executing the steps of the test.  You can see a graphic illustrating this on the Selenium site.

Getting Started

The first thing I learned is that you must launch the Selenium Server and leave it running in order to run your tests. Adam Goucher offers an Ant script to automate opening Selenium Server, running your tests, and shutting down.  I’m woefully ignorant of Ant, but it might help some of you.

For the Ant-naive like myself, let’s skip this step and just see it work.  First, download Selenium RC and upack it on your machine.  In the archive, you should see a directory called “selenium-server-1.0-beta-1″.  Using a Terminal go into this directory.  Now you can launch the Selenium Server using Java.  Obviously you have to have Java installed locally to run the server.  To test if you have Java, type:

java -version

You should get something along these lines:

java version "1.5.0_16"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_16-b06-284)
Java HotSpot(TM) Client VM (build 1.5.0_16-133, mixed mode, sharing)

Now, to start the Selenium Server, type:

java -jar selenium-server.jar

The server should spit out a bunch of text and in it somewhere should be the line:

15:10:06.062 INFO - Started SocketListener on 0.0.0.0:4444

This means the Selenium Server is now listening on port 4444. Now to run a sample test. Open a new Terminal and move into the archive directory and then into the “selenium-python-client-driver-1.0-beta-1″ directory. A quick look of the directory listing will show a few sample tests. We’re going to run the Google test. Type:

python test_google.py

Now, here’s where it gets weird for me. I’m running Firefox 3 on Mac OS X (Leopard) and here’s what happens. A new instance of Firefox launches, but nothing happens. If I quit this new Firefox instance, Firefox relaunches and the test runs successfully.

.
----------------------------------------------------------------------
Ran 1 test in 8.078s

OK

I don’t know why this happens, so I’m going to ask around and see what I can come up with.  You can close both of your Terminals at this point.

Selenium IDE + Selenium RC

My end goal here is to be able to generate at least the user input portions of the tests using Selenium IDE’s record mode, then export them (File -> Export Test Case As…) to Python, do a little custom coding, and be able to run these tests via Selenium RC.  If you do this and export your tests into a test directory then try to run them, you should get an import error on selenium.py.  You can rectify this in three different ways:

  1. Copy “selenium.py” into the directory where your Python-based tests live
  2. Put “selenium.py” into your Python apth
  3. Install Selenium via PyPI or other similar mechanism: easy_install selenium

Basically, Python needs to be able to execute the command “from selenium import selenium”.  I hope this helps you get an understanding of Selenium RC, although it still leaves some questions unanswered.  Another interesting side-effect that came up, is that Firefox 3 tries to connect to Google’s phishing and blacklist database upon launch, which lives at sb-ssl.google.com.  This throws a certificate error.  I tried to notify someone at Google about the certificate issuer for this has expired or is invalid. <shrug>.

UPDATE:
Apparently the 1.0b1 release of Selenium RC does not launch Firefox 3 properly, but the nightly build does.  Check it out, I am!

~Spanky

Eclipse for Python Development

Posted December 15th, 2008 by spanky. Comment (1).

Eclipse IDE

Eclipse IDE

Eclipse is an Integrated Development Environment (IDE) written in Python that I use for my Python projects.  I was turned on to it by Sasha Vinčić several years ago at a LovelySystems SnowSprint in Austria.  Without his help, I would probably never have given it a chance.  I’d like to go over a few quick things to get you up and running quickly with Eclipse, since at first look it’s not very intuitive.

Eclipse is written in Java, so you’ll need to have a Java RTE installed on your machine.  If you don’t have it already, this is beyond the scope of this document, but most OS’s have it available to you already, or can be installed quicky and easily.  Being written in Java is great because it runs on most platforms with very few cross-platform idosyncracies.  To me, this is great because you can avoid everyone’s platform/editor preferences and standardize on something.  The helps break down barriers to pair programming (“oh, I use emacs, and s/he uses vi, so I can’t work on their system…”) and allows development groups to pool knowledge bases in terms of troubleshooting, features, and licensing.  Anyhow, enough trying to convince you!

Download & Install

Downloading and installing Eclipse is really straightforward, so long as you have a Jave RTE installed.  The first question you’ll encouter is which version to install.  There are more than a few bundles of Eclipse suited for various types of development, including Java, Eclipse plugins, Modeling, and such.  You can review the various bundles on the Eclipse download page.  I have always used the Classic Eclipse (at the very bottom), which comes with the baseline for what you need.  There doesn’t seem to be anything geared directly towards Python developers, so we’ll just add all that as we go.  Download that, install it, and launch it.

Getting Oriented

When you first launch Eclipse, you get this weird screen that has a bunch of icons on it and no real clear way to proceed.  You can check out the online help, which I’ve found pretty useful, but let’s just give right in.  The icon you want (in Eclipse 3.4.1) is the circle with the arrow in it.  This will take you straight to the Workbench in the Project Explorer perspective.  On first launch, it’ll probably ask you to set up a folder for your Workbench to be stored in, I recommend putting in one of two places: you can put it in “My Documents\Workbench” or your OS’s equivalent (OS X: Documents) or you can put it at the root of your filesystem to save time browsing to it in terminals, diaglog boxes, etc.  Your choice.  From now on, this is where all of your Eclipse work will go.  If you decide to move it later, you can just move the folder, launch Eclipse and it will ask you what you did with it.

Now that you’re in the workbench, you should see multiple panes with tabs on them.  First good thing to know is that you can drag those tabs all over and arrange them how you want.  The first thing that I like to do is drag the Outline view under the Project Explorer in the left column.  The next thing to know is that you can minimize any section using the icon 2nd to the right (looks like a small white rectangle) in each area.  so if you want more screen real estate, just minimize what you don’t need.  Also, if you double click any tab, it’ll expand to full screen, also very useful. Finally, you can grab the edges of these areas like a framed website and resize them to your liking.  Eventually you’ll settle on exactly what’s right for you.

Add ons

One of the great things about Eclipse is the amount of add ons available for it.  We’re going to install a few of these now to get a useful environment for Python development.  Eclipse comes ready to develop for Java.  We’ll be turning that off.

Here are a few useful add ons we’ll be installing:

Subclipse: SVN for Eclipse

PyDev: Python environment for Eclipse

WebTools: Useful syntax highlighting for web-like files (HTML, CSS, etc.)

First, let’s take a look at how to add updates.  Once you get the hang of it, it’s pretty easy and nice because it automatically looks for updates, so you can stay current with new developments and search for new features.  To get to the Software Add ons manager, go to Help -> Software Updates.  If it is not selected already, click the “Available Software” tab.  On the right you should see an “Add Site…” button.  This is where you add new sites that offer Eclipse software.  Click the Add Site button and enter:

http://subclipse.tigris.org/update_1.4.x

And click OK.  This new site will show up in the list.  Click the topmost checkbox and click the “Install…” button.  Follow all the prompts, accept the licenses, etc. and when you’re all done, you should have the Subclipse Add On installed into your Eclipse.  Keep reading for how to manifest it…

Perspectives

Eclipse perspectives are basically customized collections of tabs.  In the Package Explorer, you’ll see the Outline, Problems, Console, main editor window, and such.  If you switch to another persective, the previous one is saved and you can re-arrange and customize the new perspective.  Perspectives are usually associated with some form of task or Add On, for example, the Java perspective has Java-y things on it for you, and the Subclipse perspective shows you tools for dealing with SVN.  Let’s remove the Java perspective, and add the Subclipse perspective to your perspective tab so you have easy access to it.

The perspective tab is in the upper right by default.  Click on the “Add perspective” icon (it has a plus on it), and choose “Other…”  From the window that opens up, choose “SVN Repository Exploring”, and you should notice a new icon appear in the Perspective Tab.  If not, then the perspective bar is probably too small.  You can drag it from right to left to make it bigger.  Now right click on the Java Perspective icon and choose “Close”.  You can get it back by using the process we added the SVN Perspective.  Finally, I like to make this much more compact and useful: Right click on the SVN Perspective icon and deselect “Show Text”.  Right click again and choose “Dock On -> Left”.  This is how I like it, feel free to adjust to your liking.

Now we have the SVN perspective.  Next we’ll add PyDev and we’ll add a Python Development Perspective to this bar too.

PyDev

PyDev’s website states “Pydev is a plugin that enables users to use Eclipse for Python and Jython development — making Eclipse a first class Python IDE — It comes with many goodies such as code completion, syntax highlighting, syntax analysis, refactor, debug and many others. If you want more details on the provided features, you can check here.”  To install it, follow the same procedure for the Subclipse extension, but use the PyDev Update Site URL: http://pydev.sourceforge.net/updates/

When you’re all done, you can add the PyDev Perspective as outlined above.  It’s that easy!  And if there’s ever updates to any of these plugins, you’ll be notified and prompted to update them.

Web Tools

We’ll install the Web Tools add on a little differently; this gives you an idea on how to find other features of Eclipse available from Eclipse HQ.  First, go to Software Updates.  On the Installed Software tab, you should see “Ganymede” (the codename of Eclipse 3.4.x).  Expand that section, and exapnd the “Web and Java EE Development” section.  There, you should see “Web Developer Tools”.  Feel free to add anything else you’re interested in, I added things like JavaScript Developer Tools, XML Editors, etc.  Click the Install button and you’re on your way!  The Web Developer tools adds a few great things like HTML syntax highlighting and associates .htm/.html file extensions to the HTML editor.

Word Wrap

Soft wrap is sorely lacking from Eclipse, you can add a sort-of working Add On to get Virtual Word Wrap in the editors by adding: http://ahtik.com/eclipse-update/  – Access it by right clicking in the editor and choosing “Virtual Word Wrap”.  The problem is the line numbers don’t act properly.  Speaking of Line Numbers:

Line Numbers:

Turning on line numbering is really easy.  Go to the Preferences window.  In there, go to General -> Editors -> Text Editors,  You’ll see the “Show Line Numbers” checkbox.

Wrapping Up

OK, that’s it for today.  In the future, I’m going to be figuring out how to integrate Python Unit testing into Python.  I had it wokring years ago, but I forget how.  This allowed you to write and run tests and use the debugger right from within Eclipse.

Getting Started with Selenium

Posted December 12th, 2008 by spanky. Comment (1).

Se: Atomic Number 34

Selenium is a tool that makes your life easier if you’re a web developer by allowing you to write automated tests for your website.  Selenium basically remote controls your browser using JavaScript, allowing you to script a set of actions and verify the results.  You can use it for a myriad of tasks like testing flow and error checking.  We need it to test several forms that do intake for our customers.  Currently, we have a QA team that has to fill in each form over and over, changing the input to test validation errors and the like.  This sucks and is prone to error because, unless they’re really organized, they can miss things, not to mention that it takes a ton of mindless time (waste).  My goal is to automate the testing of these forms.

The first thing I’ve noticed is that the Selenium documentation isn’t all that great.  Ian Bicking has written some stuff, and there’s a cursory overview on their documentation pages.  Like most things Open Source, the documentation is much neglected.  Maybe it’s like most things where once you’ve figured it out and set it up, it works and you never have to really bother with it again, and therefore don’t document it.  Then the next guy coming along has to fumble through it, figures it out, and quickly forgets the pain.

Second, the tutorial basically starts with “Once you’ve got Java installed”.  Here is where I stop reading, because Java is my Kryptonite and enemy.  Basically, I don’t do Java.  Sure, the Selenium Server is written in Java, and that’s their choice and I’m happy to RUN things written in Java (I use Eclipse & Poseidon for UML and love them), but I try not to deal with it directly.  If you’re not as Java-averse as I am, check out the tutorial which shows you how to get the Selenium Server running in what amounts to console mode, and mess with it.

Third, the code has been updated and the documentation has not, so the installation instructions are wrong and can cause confusion.  I’ll go over that below.

Finally, again like most Open Source things I encounter, it is assumed you know what you’re doing and there’s not much help for the person just getting started.  More on this later.

Background

First, there are several parts to Selenium.  This post is all about getting things running quickly and showing results, therefore we’re going to take the easy route and use Selenium IDE, which is a plugin for Firefox. (If you’re developing for the web and you’re not using Firefox, staple your lip to your mousepad right now.)  There are a few other pieces to Selenium that I’m going to fuss with later, and I’m really gonna try to figure out Selenium RC, since it allows you to use Python, which I love.  Here’s an overview of the other parts of Selenium:

Selenium Core:
The core stuff that does the work
Selenium IDE:
The plugin for Firefox.  Has hugely useful “recording” mode that watches what you do, records it, and helps you learn. Saves as other formats, FTW!
Selenium RC:
RC stands for Remote Control. It runs from real code in the language of your choice, allowing you to write more complicated tests, in say, Python, rather than the IDE syntax, which is HTML tables.  Yes.  HTML tables.
Other:
There’s also some other parts like Selenium on Rails, and Selenium Grid.  I am not interested in these (yet).

So now that you see what’s available, we’re gonna play with the IDE.

The Selenium IDE

The Selenium IDE is really easy to install. You need to be using Firefox for this URL to work, as it’s a link right to an XPI file: http://release.openqa.org/selenium-ide/1.0-beta-2/selenium-ide-1.0-beta-2.xpi

It should install right into your browser and ask you to restart Firefox.  See you in a second!

A Sample Test

Now that you have the plugin installed, you should see “Selenium IDE” listed under the Tools Menu.  Yeah, go ahead and open it!  A little window will open, and it’s ready to record your actions.  Let’s do a quick test on Google.  Open a new window and go to http://google.com, then type “kapanka.com” into the search box and click the “Google Search” button.  A few commands should have been automatically entered into the Selenium IDE window.  Under the last entry, you’ll see a green line.  This is “where you are” in the recording.  Also, note that Google was entered into the Base URL box at the top.

Now we’re going to test something.  Click in the Selenium IDE window if you’re not there already.  Now click below the green line to enter a new line, then click in the “Command” field.  This is a dropdown list of the commands available and  should autocomplete if you start typing.  Type or choose: “assertTextPresent” in the Command field.  Skip the Target field, and enter “Bukkit” into the value field.  What this will do is test whether the text “Bukkit” is found anywhere on the results page.

Now it’s time to run the test.  Before we run it, there’s a hidden pane that we need to open.  If you do not see a column on the left of the Selenium IDE window with the words “TestCase” at the top, then click the thin vertical dotted line at the left.  This should open a list of available tests.  Select the “untitled” test.  Now, click the icon that has a Green Arrow on it (either one will do, one is Run All Tests, the other, Run This Test, and you only have one test right now).  If you watch carefully, you’ll see each step in the test get highlighted green as it runs.  The last step is green-er because it actually tests something.  Also, you’ll notice that it opened Google.com, typed my domain name in, hit “Google Search” and verified that “Bukkit” was found in the results.  Neat-o, huh?  If you’re having fun reading this so far, I recommend clicking the Obama Haz A Bukkit link and click on the ads there!

Next Steps

OK, so that was a pretty stupid test, but you get the idea.  You can do as much as you’d like in record mode (don’t forget to turn it off when you’re done recording!), then run the entire thing and watch it all happen real quick.  But this alone isn’t very useful.  What we want to do is save these tests so we can run a bunch of them at once.  This is where we get the concept of the Test Suite.  A Test Suite is a group of tests that can be run all at once.

Installing on the Server

Now we want to install Selenium onto your webserver so that we can record a bunch of tests with the IDE, then save them somewhere and run them all at once.  Selenium has to be installed at the same domain name as what’s called the AUT (Application Under Test).  This is because JavaScript’s security mechanism doesn’t allow it to do what’s necessary cross-domain.  This is a good thing.  You can find out more about this by poking around the Selenium site, but it suffices to say that you cannot test Domain B from Domain A.

Click for license

Click for license

Therefore you’re going to need access to your web server, but if you’re developing without server access, or at least a local development environment running, you can take your mousepad-stapled lip and feed it into your office paper shredder.  You do have access to your server, right?

OK, download Selenium and unpack it on your local machine.  We’re gonna poke at it a bit before putting it onto your web server.  You can find the appropriate download on the Selenium Download Page.  Once you’ve got it downloaded and unpacked look into the resulting folder.  You’ll see the “core” folder, and the “tests” folder.  The tests folder is super-useful because it gives you a great place to look for examples.  In fact, that folder has a set of DogFood tests that test basically every function available to Selenium.  This is the first thing we’re gonna run.  Rename the folder you unpacked from “selenium-core-0.x.y” to just plain “selenium”, and upload this folder to the root of your web server.

All done?  Perfect.  Now navigate to this folder on your server: http://<your-domain-here>/selenium and you should see the Selenium default page.  Click the topmost link: Selenium TestRunner.  This takes you to the TestRunner environment that you will eventually use to run your Test Suites.  On the Test Runner page, click the “GO” button to load the default Test Suite from the Selenium “test” folder.  You should see all of the tests load into the leftmost pane.  Ready?  Click the “Run All Tests” icon (Green arrow, 3 lines) in the rightmost pane and watch it go!  While its running, you’ll see the AUT in the bottom pane.  Pretty cool, huh?

Now you should have: 74 tests run, 1 failed. 583 commands passed, o failed, 1 incomplete.

Writing your own tests

Here’s where we tie the two together.  You should create a directory on your web server called “tests”.  You can just dump all of your tests in there, or make a “stests” or “ftests” (selenium tests or functional tests) subdirectory.  This is where you’ll put your Test Suite and individual tests.

Open your website in Firefox, and also open the Selenium IDE.  First you’ll want to make a new Test Suite by using File -> New Test Suite.  Then File -> Save Test Suite As…  Save the Test Suite as MyTestSuite.html on your local machine.  Next, you’ll want to record a new test for your website.  Do some clicking, add some assertions, and when you’re all done, choose File -> Save Test Case and save it as TestMyFirstTest.html (by convention, test files start with the word Test).  Now, edit MyTestSuite.html in your favorite editor.  The format of this file is an HTML table.  You should see that the first row of the table is the Title of the Test Suite, and the second row is “Untitled”.  Replace the first column value with “TestMyFirstTest.html” and the second column with “My First Test”.  Save this file and upload both of them to your webserver in the /tests/stests directory.  Now you’re ready to run your Test Suite.

Running Your Tests

OK, back to the Selenium of your website in Firefox.  This time when you click into the Selenium TestRunner, you’ll want to type the name of your Test Suite into the box on the uppermost left field.  Type: “/tests/stests/MyTestSuite.html” and click “GO”.  You should see your “My First Test” load up in the leftmost frame.  Run the test!

Wheeee!

If everything went smoothly, your test should have run with all green.  My fingers are killing me from typing and mousing for the past hour straight.  Next post…working on getting Selenium RC to run.  I hope this helped you get started with Selenium, and sorry about the gross picture of the shredded dog tongue.  Blech!

~Spanky

Statement of Purpose

Posted December 12th, 2008 by spanky. Comments Off.

That’s all official sounding, huh? Scared you, did I? Like, is this going to suck, or what? Well, that’s your opinion to have, so have at it, but I’ll do my best.

The idea here is to flounder through all the things that I do…and you get to watch!  I’m constantly learning, growing, and getting frustrated with stuff (and then trying to fix it), so if you follow along, pay attention, and keep a good sense of humor, you just might learn something.  With that said, I’ve already taken up too much time with this silly intro.  Let’s get started…