technology from back to front

Archive for April, 2010

Year at LShift – in photos

Read more…

by
marek
on
30/04/10

Design sketches for Clojure coverage tool

I like to write unit tests for my code and I also like to know whether my unit tests are actually testing my code. In Java I would use Maven and Cobertura to measure how
much of my code is actually exercised, and when I bend my mind around Haskell I use HPC.

I have been experimenting with Clojure and it has a nice testing library but the only way I have found to measure coverage is to use Cobertura and squint at the generated class names to work out what I haven’t covered. So I have started on the road to creating a coverage tool for Clojure written in Clojure. This blog entry contains my initial steps and design sketches towards creating the tool.

Ideally I’d like to measure my coverage like this:

(ns some.tests
  (:use [some.functions])
  (:use [coverage.cover])
    (:use [clojure.test]))

(deftest test-something
   (cover '(foo bar)                   ; cover foo and bar
      (is (= [1 2 3] (foo 1 2 3)))
      (is (= [2 4 6] (bar 1 2 3)))

        (is (= [100 100] (coverage foo))) ; check coverage
      (is (= [100 100] (coverage bar)))

       (store-coverage)))                ; store report to file

That isn’t functional code yet and may not be what I finally produce, it might not even be valid Clojure since I haven’t even bashed it into a REPL yet.

As Clojure is a Lisp, and we are testing our own code – i.e. we have the source code – we should be able to measure the coverage using Clojure. This can achieved by rebinding the functions under test with instrumented functions;
this is what I envisage the cover function is doing:

(cover '(foo)
  ; all calls to foo here actually call foo'
)

Which can be achieved using a binding function:

(binding [a b)]
   ; all calls to a here are actually calls to b
)

So assuming I can write the cover function I will need to instrument a function. Let’s start simply and ignore the complicated stuff such as conditional statements and multiple bodies until later. If we have this simple function

(defn foo [a b c] (+ a (- b c)))

I would like an instrumented version to wrap each s-expression with a function that records that the s-expression has been called, for now we will just print a message.

(defn foo-wrapped [a b c]
  (do
   (prn :wrap)
       (+ a
          (do
           (prn :wrap)
           (- b c)))))

Testing that in the REPL seems to reveal that I am moving in the right direction:

user=> (foo 1 2 3)
0
user=> (foo-wrapped 1 2 3)
:wrap
:wrap
0
user=>

To convert the first function to the instrumented function I need a couple of auxiliary functions and a macro:

(defn record [] (prn :wrap))

(declare wrap-seq)
(defn wrap [form]
  (cond
    (seq? form)
         (list 'do (record) (wrap-seq form))
      :else form))

(defn wrap-seq [xs]
  (for [x xs] (wrap x)))

(defmacro cover
  [args & body]
   (let [fn-name (when (symbol? args) args)
          args (if fn-name (first body) args)
               body (if fn-name (next body) body)]
   (fn ~@(if fn-name (list fn-name args) (list args))
          ~@(wrap (first body)))))

If you know some Clojure that code demonstrates some of the problems I haven’t solved yet when measuring coverage, for example the :else clause will need to be covered as well as functions in binding statements. Testing that code in the REPL gives us a reasonable result:

user=> (def x (cover [a b c d] (+ a (- b c (* a d)))))
#'user/x
user=> (x 1 2 3 4)
:wrap
:wrap
:wrap
-4
user=>

So if I now replace the record function with something else I may be able to generate some coverage for a function. I am going to use a map held by a ref to store the coverage information, a function to register a particular
s-expression with the ref and a function to increment the count.

(def coverage-records (ref nil))

(defn covering [form]
  (dosync (alter coverage-records assoc form 0)))

(defn- inc-map [map key]
  (if (contains? map key)
    (assoc (dissoc map key) key (inc (get map key)))
    map))

(defn inc-coverage [key]
  (dosync (alter coverage-records inc-map key)))

Lets test that:

user=> @coverage-records
nil
user=> (covering :x)
{:x 0}
user=> (covering :y)
{:y 0, :x 0}
user=> (inc-coverage :x)
{:x 1, :y 0}
user=> (inc-coverage :y)
{:y 1, :x 1}
user=> (inc-coverage :x)
{:x 2, :y 1}
user=> @coverage-records
{:x 2, :y 1}
user=>

If I modify our wrapping functions I can create the coverage records ready to be incremented.

(defn wrap [form]
  (cond
    (seq? form) (do
      (covering (str form))
      (list 'do `(record) (wrap-seq form)))
    :else form))

Testing that code:

user=> (def x (cover [a b c d] (+ a (- b c (* a d)))))
#'user/x
user=> @coverage-records
{"(* a d)" 0, "(- b c (* a d))" 0, "(+ a (- b c (* a d)))" 0}
user=>

And that is as far as I have got. I need to change my record function to increment the coverage records, make my wrap function cope with conditionals and other complexities and write my rebinding function. Hopefully next month I will have moved it along a little bit further.

by
tim
on
27/04/10

SpringSource / VMWare Acquire Rabbit Technologies

SpringSource, a division of VMware, Inc. today announced the acquisition by VMware of Rabbit Technologies, Ltd, a company set up by LShift and partners Monadic and CohesiveFT.

Read the full story

by
mike
on
14/04/10

SpringSource / VMWare Acquire Rabbit Technologies

SpringSource, a division of VMware, Inc. today announced the acquisition by VMware of Rabbit Technologies, Ltd.

Rabbit Technologies is an open source software company based in the United Kingdom. SpringSource will add the RabbitMQ open messaging system into its suite of technologies that reduce the complexity associated with development, deployment and management of enterprise applications.

LShift has been involved in the development of RabbitMQ from building the first prototypes and then providing the subsequent engineering and development backbone to the project. LShift founded Rabbit Technologies Ltd alongside our partners at Monadic and CohesiveFT.

LShift EO, Mike Rowlands, said “We are intensely proud of our contribution to making RabbitMQ the market leading AMQP solution, and we welcome SpringSource’s acquisition of Rabbit Technologies as a confirmation of the quality of the software we have produced and in terms of its ongoing potential, as it will see the resources of VMWare committed to its further success.”

by
Administrator
on
13/04/10

Debian build-depends metapackages

When I’m doing development on an existing software project, and especially when I’m trying to bugfix something with a Debian package, I find that I install random packages I need to rebuild something, and then later on I’m wondering why I’ve got those installed. I tend to try to keep with the philosophy that the bits of software I’m using are pretty knowledgeable about whatever they’re intended to do, and so trusting them to make smart decisions is a good idea. For package managers, this means I should only keep track of the software that I actually use, and tell the package manager that everything else has been automatically installed and can therefore be removed when they cease to be a dependency of something I actually need. Having packages that I only installed for building something else without a record of that in the package management system breaks that mental model.

Enter dh-builddep-metapackage (the naming is inline with the names used by the debhelper scripts used for other debian packaging stuff). dh-builddep-metapackage builds build-dependency metapackages in order to ease package
management for package rebuilders. In effect, it builds a “<package name>-builddep” package that has no content, but depends on everything that the existing package build-depends on. By using dh-builddep-metapackage to create metapackages rather than using “apt-get build-dep”, I keep a record in the package management about why I need a particular development package, and can remove the dependant packages when I’m no longer working with the relevant source package.

I think someone’s done this before, but some work with Google didn’t find it, and it was an interesting exercise anyway. Standard usage is “dh-builddep-metapackage -b <package name>”, which will create the metapackage data and build the package for you using dpkg-buildpackage. A folder called “<package name>-<package version>” will be created in the current local directory, and if an existing folder exists then dh-builddep-metapackage will refuse to overwrite it (unless you give the -o/–overwrite option).

So far I’ve used it a few times, and it’s quite nice to have those packages around to remind me about the dependencies. I’m considering building a full repository with *-builddep packages for everything in the Debian archives, but I’d like to make sure I’d use this enough first.

by
Tom Parker
on
12/04/10

Search

Categories

You are currently browsing the LShift Ltd. blog archives for April, 2010.

Feeds

Archives

2000-14 LShift Ltd, 1st Floor, Hoxton Point, 6 Rufus Street, London, N1 6PE, UK+44 (0)20 7729 7060   Contact us