chris blogs: May 2007

30may2007 · Analyzing the JRuby test suite

One of the biggest Ruby unit test suites in existance is JRuby’s, which weights (all external suites included) a whopping 39kLOC. It is split into some big subprojects:

  • The JRuby test suite (10kLOC)
  • The Rubinius test suite (8.4kLOC)
  • The Rubicon test suite (5.8kLOC)
  • The BFTS (4.3kLOC)
  • The Matz Ruby Interpreter test suite (4kLOC)

(The other ~6kLoc are benchmarks and Java unit tests, which are not relevant here.)

I have analyzed each of them according to these factors:

  • Number of test cases (contexts)
  • Number of tests (specifcations)
  • Number of assertions (shoulds)
    • how many are negated
    • what do they test

I’ll go through each test suite and present the numbers. Please note that they were made with some hacked-together scripts and may not be totally accurate, but they should show the big picture. All numbers are based on checkout r3767, last changed 2007-05-30 07:52:31 +0200.

The JRuby test suite

The JRuby test suite uses minirunit and Test::Unit for its tests. The minirunit part has 2747 assertions, but no specially marked test cases. The most used assertions were:

  • test_equal (1695)
  • test_ok (400)
  • test_exception (277)
  • test_tree (118)
  • test_no_exception (73)
  • test_check (69)

There are a lot non-xUnit assertions defined, which only make up a small part of the suite: the often used ones are test_tree (assertions about the parse tree) and test_marshal.

Negated assertions occur as test_no_exception and test_fail, and make up about 5.6%. (Including 71 cases of test_ok with a negated expression.)

The small mri test suite (minirunit too) has 260 assertions, of which 226 are test_ok, 19 test_equal and 15 test_check.

The Test::Unit part of the suite has 40 test cases with 244 tests. There are 568 assertions, of which 33 (5.8%) are negated. Most used are:

  • assert_equal (331)
  • assert_raises (38)
  • assert_parse_only (38)
  • assert_inspect_evaled (28)
  • assert_argerr (20)
  • assert_cycle (18)

Other non-xUnit assertions are: test_to_yaml, test_eval_inspected, test_path_segments.

The Rubinius test suite

The Rubinius test suite uses a small clone of RSpec called mini_rspec. It contains 117 contexts with 1046 specifications. There are 2513 shoulds, of which 15 are negated (0.6%).

The most used shoulds were:

  • should == (1765)
  • should == true (304)
  • should == false (106)
  • should_raise (141)
  • should == nil (87)
  • should_include (35)

should_receive (12) was the only custom should found.

The Rubicon test suite

The Rubicon test suite uses Test::Unit and has 42 test cases with 480 tests. Of 2316 assertions, 18 are negated (0.8%).

Most used assertions were:

  • assert_equal (1941)
  • assert_flequal (107)
  • assert_nil (102)
  • assert_raise (79)
  • assert_same (30)

Non-xUnit assertions are assert_bag_equal.

The BFTS

The Big Fucking Test Suite consists of 13 Test::Unit test cases with 359 tests. There are 1914 assertions, 34 are negated (1.8%).

Most used where:

  • assert_equal (1706)
  • assert_nil (85)
  • assert_raises (76)
  • assert_same (23)

There are no non-xUnit assertions in the BFTS.

The MRI test suite

The MRI test suite consists of 46 Test::Unit test cases with 166 tests. There are 1178 assertions, of which 28 are negated (2.3%). Most used were:

  • assert_equal (982)
  • assert_raises (69)
  • assert_nil (43)
  • assert_instance_of (17)

Non-xUnit assertions are: assert_arity, assert_eval_inspected, assert_inspect_evaled.

Conclusion

N.B.: These unit test suites test language implementations and not highlevel libraries or applications, therefore these results are not directly applicable for general testing frameworks. It would be great if someone could do tests like these for big libraries (Rails) or big applications.

The main assertions used are tests for equality (and especially true, false and nil) and tests for exceptions. Only a small part of assertions are negated, and these mostly check that nothing is raised.

xUnit assertions cover over 90% of all assertions, but custom and user-defined assertions simplify testing by abstracting common code and making test cleaner and clearer.

Future testing frameworks (especially for language test suites) should optimize for these features.

NP: Bob Dylan—Forever Young

26may2007 · Verweigerung

Endlich (nach über zwei Monaten) ist mein Kriegsdienstverweigerungsantrag durch, und ich darf somit den Dienst an der Waffe verweigern.

Da meine Verweigerung anders als die vielen anderen, die man so im Netz findet, nicht mit religiösen Gründen oder der Erziehung wegen argumentiert, könnte sie auch anderen Verweigerern nützlich sein. Hier daher der Volltext.

Beweggründe für meine Kriegsdienstverweigerung

Ein Krieg ist ein Waffenkonflikt, der unter Einsatz erheblicher Mittel ausgeführt wird.

Unter Ausübung von Gewalt wird also versucht, einen Konflikt zu bewältigen, oder eigentlich, wie Clausewitz schreibt: “den Gegner zur Erfüllung unseres Willens zu zwingen”.

Aus eigener Erfahrung weiß ich aber, dass Gewalt aber nie eine Lösung ist, sondern stets Gegengewalt erzeugt: an Konfliktbekämpfung ist daher nicht zu denken. Es ist jedoch meine feste Überzeugung, dass es für jeden Konflikt eine friedliche und dauerhafte Lösung gibt.

Die Anwendung von Gewalt als versuchtes Mittel zur Konfliktbewältigung ist jedoch gegen die Natur des Menschen, oder genauer: gegen die menschliche Natur. Unsere Menschlichkeit erlaubt es uns, Konflikte auf friedlichem Wege zu lösen, ohne zu töten und zu zerstören.

In der Geschichte gibt es genug Beispiele dafür, dass eine friedliche Lösung von Konflikten möglich ist, als Beispiel seien hier Mahatma Ghandi und Martin Luther King genannt.

Ein weit größeres Problem als die Sinnlosigkeit eines Krieges ist jedoch das Leid und die Grausamkeit für die betroffenen Menschen: Sowohl die Zivilbevölkerung als auch die Soldaten, die ja trotzdem Menschen sind, werden oft schwer verwundet und tragen physische und auch große psychische Schäden davon.

Nicht nur durch meine Erziehung, sondern auch durch die reine Vernunft ist es mir daher unmöglich Kriegsdienst zu leisten. Dieser schließt nämlich nicht nur den Dienst an der Waffe ein, deren Zweck es ja ist, den Gegner durch letale Gewalt zu kontrollieren, sondern beinhaltet sämtliche andere Tätigkeiten, deren Sinn in der Planung, Vorbereitung und Durchführung von Waffengewalt endet.

Selbstverständlich bin ich nicht der erste, der zu diesem Schluss kommt. So fordert Kant, der wohl wichtigste deutsche Philosoph, in seiner Schrift “Zum ewigen Frieden” von 1795: “Stehende Heere (miles pepetuus) sollen mit der Zeit ganz aufhören, “[d]enn sie bedrohen andere Staaten unaufhörlich mit Krieg, durch die Bereitschaft, immer dazu gerüstet zu erscheinen”. Auch wenn die Bundeswehr nur als Verteidigungsarmee gedacht ist, so hat sie doch ein stehendes Heer, und kann daher stets Krieg führen. Wieviel Leid wäre der deutschen und der Weltgeschichte erspart worden, hätte man auf Kant gehört.

Kant erkennt weiterhin, dass Frieden kein Naturzustand ist, sondern gestiftet werden muss, und dabei stimme ich gänzlich zu. Die Kraft und Vernunft der Menschen sollte daher dazu verwendet werden, Frieden zu stiften, und nicht etwa Kriege zu führen. So will auch ich meine Kraft zum Wohl der Bevölkerung und nicht des Krieges verwenden und Zivildienst leisten.

Kein Mensch will sich erschießen lassen, will gefoltert werden oder für einen nichtigen Zweck wie Landesgrenzen sterben. Selbst wenn mein eigenes Leben auf dem Spiel stünde, würde ich aber auch nicht schießen, foltern oder töten können; nicht aus eigener Überzeugung, und schon gar nicht auf Befehl.

Befehl und Gehorsam, wie sie im Kriegsdienst an der Ordnung sind, stehen dort über der Vernunft: Der Soldat hat zu befolgen, was ihm befohlen wurde. Diese Aufgabe der Vernunft, und der damit einhergehende Verlust der Selbstkontrolle, kann grausamste Folgen annehmen, die angesichts der deutschen Geschichte keiner weiteren Erläuterung bedürfen. Als aufgeklärter Mensch ist es für mich unvorstellbar, durch Zwang zum Gehorsam zu einem gedankenlosen Ausführungsorgan reduziert zu werden.

Ich habe mich ernsthaft mit der Vorstellung, auf Befehl Menschen töten zu müssen, auseinandergesetzt und stellte fest, dass allein schon die Vorstellung davon weder mit meinem Gewissen noch mit meinem Weltbild vereinbar ist.

Ich bin daher felsenfest überzeugt, auf keinen Fall zum Teil dieser Kriegsmaschinerie werden zu wollen, und anderen Menschen, seien es sogenannte “feindliche” Soldaten oder auch der Zivilbevölkerung, Leid jeglicher Art anzutun, auf sie zu schießen, sie zu verletzen oder gar zu töten.

Der Bundeswehr oder irgendeiner anderen Streitkraft zu dienen würde meine Wertvorstellungen massiv untergraben.

Um meiner Überzeugung zu folgen und mich aktiv dafür einzusetzen, sehe ich den Zivildienst als eine gute Möglichkeit an, meine Pflicht als deutscher Bürger gegenüber Staat und Gesellschaft zu erfüllen. Ich habe mich bereits nach Zivildienststellen erkundigt und mich schon bei mehreren beworben. Ich will die mir vom Staat gegebene Chance nutzen, um Erfahrungen zu sammeln, die mir auf meinem weiteren Lebensweg bestimmt nützlich sein werden.

Daher bitte Sie hiermit darum, meine Kriegsdienstverweigerung nach Artikel 4, Absatz 3, Satz 1 des Grundgesetzes anzuerkennen.

Für mich hat’s geklappt, aber alles natürlich ohne Gewähr.

Viel Erfolg.

NP: Bob Dylan—Masters Of War

16may2007 · Rack 0.2, a modular Ruby webserver interface

Today I’m proud to release Rack 0.2.

Rack provides a minimal, modular and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call.

The exact details of this are described in the Rack specification, which all Rack applications should conform to.

Supported web servers

The included handlers connect all kinds of web servers to Rack:

  • Mongrel
  • Mongrel/Swiftcore (require it before Rack.)
  • WEBrick
  • FCGI
  • CGI

Any valid Rack app will run the same on all these handlers, without changing anything.

Supported web frameworks

The included adapters connect Rack with existing Ruby web frameworks:

  • Camping

These frameworks include Rack adapters in their distributions:

  • Ramaze
  • Maveric
  • Racktools::SimpleApplication

Available middleware

Between the server and the framework, Rack can be customized to your applications needs using middleware, for example:

  • Rack::URLMap, to route to multiple applications inside the same process.
  • Rack::CommonLogger, for creating Apache-style logfiles.
  • Rack::ShowException, for catching unhandled exceptions and presenting them in a nice and helpful way with clickable backtrace.
  • Rack::File, for serving static files.

All these components use the same interface, which is described in detail in the Rack specification. You can choose to use them exactly in the way you want.

Convenience

If you want to develop outside of existing frameworks, implement your own ones, or develop middleware, Rack provides many helpers to create Rack applications quickly and without doing the same web stuff all over:

  • Rack::Request, which also provides query string parsing and multipart handling.
  • Rack::Response, for convenient generation of HTTP replies and cookie handling.
  • Rack::MockRequest and Rack::MockResponse for efficient and quick testing of Rack application without real HTTP round-trips.

rackup

rackup is a useful tool for running Rack applications, which uses the Rack::Builder DSL to configure middleware and build up applications easily.

rackup automatically figures out the environment it is run in, and runs your application as FastCGI, CGI, or standalone with Mongrel or WEBrick—all from the same configuration.

Where can I get it?

You can download Rack 0.2 here:

Alternatively, you can checkout from the development repository with:

darcs get http://chneukirchen.org/repos/rack

(Patches using “darcs send” are most welcome.)

Installing with RubyGems

A Gem of Rack is available. You can install it with:

gem install rack

I also provide a local mirror of the gems (and development snapshots) at my site:

gem install rack --source http://chneukirchen.org/releases/gems

History

  • March 3rd, 2007: First public release 0.1.

  • May 16th, 2007: Second public release 0.2.

    • HTTP Basic authentication.
    • Cookie Sessions.
    • Static file handler.
    • Improved Rack::Request.
    • Improved Rack::Response.
    • Added Rack::ShowStatus, for better default error messages.
    • Bug fixes in the Camping adapter.
    • Removed Rails adapter, was too alpha.

Contact

Please mail bugs, suggestions and patches to .

You are also welcome to join the #rack channel on irc.freenode.net.

Thanks to

  • Michael Fellinger, for the helpful discussion, bugfixes and a better Rack::Request interface.
  • Christoffer Sawicki, for the Rails adapter.
  • Tim Fletcher, for the HTTP authentication code.
  • Armin Ronacher, for the logo and racktools.
  • Aredridel, for bug fixing.
  • Gary Wright, for proposing a better Rack::Response interface.
  • Alexander Kellett for testing the Gem and reviewing the announce.
  • Marcus Rückert, for help with configuring and debugging lighttpd.
  • The WSGI team for the well-done and documented work they’ve done and Rack builds up on.

Copyright

Copyright (C) 2007 Christian Neukirchen http://purl.org/net/chneukirchen

Rack is freely distributable under the terms of an MIT-style license.

Links

Rack: http://rack.rubyforge.org/
Rack’s Rubyforge project: http://rubyforge.org/projects/rack

Camping: http://camping.rubyforge.org/
Ramaze: http://ramaze.rubyforge.org/
Maveric: http://maveric.rubyforge.org/
racktools: http://lucumr.pocoo.org/trac/repos/racktools/

f1063711f228d19875a3211d71308b5c  rack-0.2.0.tar.gz
fad21b5fac8790fe6bf295fefdac5816  rack-0.2.0.gem

NP: Aimee Mann—Clean Up For Christmas

14may2007 · Abi-Gag im PG

Mir fällt zum Abi-Gag im PG nichts ein. Hätte man mir nicht gesagt, dass er heute sei, hätte ich ihn nicht bemerkt.

NP: Aimee Mann—Little Bombs

Copyright © 2004–2016