That Test Framework

A few weeks ago I dreamt about a unit testing framework for Python.  Well, I’ve put together a proof-of-concept prototype.  What you can do with it:

  • Set up tests and nested test suites
  • Provide per-suite or per-test setup and teardown on test suites
  • Provide explicit ordering to tests in particular test suites
  • Write parameterised tests

What you can’t yet do:

  • Put multiple tests in a test suite and say “if this one fails, don’t run the others”

You can download my prototype here (licensed under GPLv2).  To play with the examples:

  • run “python -i thattest.py”
  • run the example tests by calling the tests suites, e.g. testSuiteA()
  • this will return a tuple of the form (passes, failures, skipped)
Posted in short | Tagged , , , | Comments Off on That Test Framework

Window Manager Woes

I’ve been playing around with different window managers for my Ubuntu installation.  At work in particular, I find it really useful having a tiling window manager because (a) it improves my efficiency because the keyboard shortcuts help to cut down on the time it takes to move my hand between the keyboard and mouse, and (b) it severely reduces the stress of having to flip between a whole bunch of overlapping terminal windows and editor windows.

Here’s a brief summary of my travels in WM land:

  • wmii—an excellent tiling window manager in my experience.  As well as all the things that come with most tiling window managers, it has a clean interface through which programs can query the WM and send it commands.  So, for instance, I wrote a simple script which meant that pressing Alt+G would pop up dmenu with the titles of all open windows, so I could select a window by searching for part of the window’s title bar text.  I had grand plans for other extensions for wmii too, but these were cut short when work got me a laptop.  You see, wmii is terrible at handling multiple monitors.  And whatever window manager I use at work, I absolutely need it to be able to use both the laptop’s monitor and my external monitor.  And so I travelled onwards…
  • i3—very similar to wmii in many respects, except that i3 has excellent support for multiple monitors.  You can simply use xrandr to set up the monitors however you want, and the window manager adjusts itself to your settings.  Indeed, i3 was created by a wmii user who was annoyed at its poor support for multiple monitors.  The down-side to i3?  Yes, there is a downside.  i3 does not have the extensibility of wmii.  You can query some things about i3, and issue some commands (through a unix socket), but at the time of writing you can’t do anywhere near as much cool stuff as you can with wmii.  With i3, basically all you can talk to the window manager about are the status of monitors, and how many virtual desktops there are.  And so I explored further…
  • PyWM—this sounds really cool!  A window manager written in Python.  Why that’s just what I want…  It doesn’t matter that it’s not a tiling window manager, if it’s written in Python I can hack it to display windows in whatever layout I like, right? …  Right? …  Is anyone out there?  Hello?  It seems PyWM has been abandoned.  The webpage has not been updated since 2006, and that was shortly after the project changed hands after 2 years of inactivity.  I had a quick try at compiling this one from source, but I ran into all sorts of problems, not least of which were PyWM’s dependencies on old libraries.  Perhaps a braver soul than I can conquer PyWM.  But for the rest of us… onwards!
  • Qtile—what’s all this?  A tiling window manager written in Python?  Surely that’s too good to be true…  Well the website says “2010” at the bottom, so it may well be up-to-date.  I tried building this window manager, and ran into the opposite problem that I had with PyWM: Qtile depends on versions of libraries which are newer than the stable versions in the Ubuntu repositories.  I had a brief go at getting these dependencies and building it anyway, but had no success.  Still, this project looks quite promising.  Perhaps when I have some days to kill I’ll come back to it.
  • Awesome—now this looks interesting.  A window manager that’s completely scriptable in the Lua programming language.  Unfortunately I’ve never programmed in Lua before.  Thankfully there seem to be a number of decent tutorials around.  Next time I’m feeling both fed up with my current WM and inspired to experiment, I shall have to give Awesome a proper go.  It certainly sounds like a good thing.  But until then, I think I’ll stick with i3.
Posted in midlength | Tagged , , , , , , , , , , , , , , , , | Comments Off on Window Manager Woes

Python Unit Testing

I’ve had to write and maintain Python unit tests both for work and for Trosnoth.  I’ve played around with py.test and nose, and have done a tiny bit with trial (for twisted).  As a result I’ve come up with the following wish list for a Python unit testing framework.

  • Being able to constrain test order—in particular, I’d like to be able to say “If test A fails, do not run test B.”  This should make it easier to identify the true cause of certain problems.
  • Test code should be readable—some unit testing frameworks use lots of magic which can make it easy to write tests, but when you come back and read the tests later, it can be really confusing to find where certain things are defined (e.g. py.test funcargs).
  • Generating many similar tests should be easy—if you want to run the same test with x=1, 2, 5, 15 and 28, you should not have to write 5 separate functions.  You should not have to write a class.  You should be able to write a function and specify that it should be called with multiple values.
  • Setup and teardown for groups of tests—pretty much every test framework has this, but I thought it was worth mentioning anyway.  It could be done better too.  For instance, in some situations it would be useful to have nested scopes where each scope has a setup and teardown.

Those are the main things I can think of right now.  At some stage I may implement a simple framework based on these ideas, just for fun.  If I do, I shall post about it on this blog.

Posted in midlength | Tagged , , , , | Comments Off on Python Unit Testing

Behold, My Long Silence is Now Broken

Due to the extended Blogetery.com outage my blogging was interrupted and now it’s taken me a while to get back into it.  A few things to note:

  • Now that my blog’s been restored, the formatting of old articles is terrible.  At some stage I may go back through and fix this, but not just yet.  Be patient.
  • I’ve had to change the blog theme because the old theme is no longer in the available options.

Perhaps I need to get a Linode so I can host my own blog.

Posted in short | Tagged , , | Comments Off on Behold, My Long Silence is Now Broken

Talking Back to Mum

The Aim

While doing some programming on the HATE terminal emulator, I came across an interesting idea: I wanted to be able to type a command into bash (from within HATE), that would leave the current bash session running, but open a new terminal, potentially running a particular process. For instance, I might type “hatecmd new vim” and it should open a new vim terminal within HATE. I could then use HATE to switch back and forth between bash and vim.

The Problem

When bash is run within HATE, the bash process is a child process of the HATE process. When I type a command in bash, it spawns a new child of the bash process. For this command to get HATE to do something (open a new terminal), it needs to communicate with an ancestor process that knows nothing about it. There are standard ways for processes to talk to one another in the unix world, but they usually rely on either (a) the processes knowing about each other (such as a server which has many child processes to handle network requests—the server process knows about its children), or (b) there being one system-wide process being talked to (such as a system-wide service listening to a named pipe). Neither of these conditions apply to HATE, as one or more users may run HATE one or more times, and HATE doesn’t know about the processes that bash spawns.

Of Locks and Signals

I considered a number of alternatives for tackling this problem. One involved sending and catching user signals, obtaining locks and writing application data to disk for other processes to read. The more I thought about this approach the more and more problems I came across. So I abandoned this approach in favour of another.

There’s Already a Way

Thinking about the problem, I realised that there’s already a way for processes that are run within a pseudo terminal to send messages to the terminal—via escape sequences. For instance, certain commands will ask to change the title of the terminal they’re running in. This is often used so that when you ssh into other machines, the terminal title reflects the machine you’re on. To do this, the shell on the remote machine writes a special sequence of characters which are read and translated by the pseudo terminal which, rather than printing the characters to the display, uses them to change the window title.

So, this gives two alternative solutions to our problem:

  1. Write a new pseudo terminal for HATE with its own special escape sequences that can be used to open new tabs. This option is very involved and, since I know very little about writing pseudo terminals, would take me quite a while to get my head around.
  2. Piggy-back an existing escape sequence, such as “change title”.

I adopted the second approach, with a few measures to ensure that this was not done accidentally. Specifically:

  1. Each instance of HATE generates a random set of characters which are that instance’s HATE ID.
  2. The HATE ID is inserted into the environment of child processes as $HATE_ID.
  3. In order to run a special HATE command, the program hatecmd will:
    1. Check that $HATE_ID exists and print an error if not.
    2. Set the terminal title to “HATECMD:$HATE_ID:<command>”.
    3. Wait for half a second in case HATE wants to print some output to the terminal.

Celebrate!

I implemented this and it works fantastically. I even wrote the following script so that vim will open in a new terminal when run from within HATE:

#!/usr/bin/python

import os
from subprocess import Popen
import sys

if 'HATE_ID' in os.environ:
    cmd = ['hatecmd', 'new']
else:
    cmd = []

cmd.append('/usr/bin/vim')
cmd.extend(sys.argv[1:])

p = Popen(cmd)
p.communicate()
sys.exit(p.returncode)
Posted in midlength | Tagged , , , | Comments Off on Talking Back to Mum