Testing / TDD

TDD, BDD og automatisert testing; viktige begreper for den moderne utvikler. Jeg er ingen guru, men deler gjerne min erfaring på dette her likevel.

En agurktest

Om du ikke har levd under en stein det siste året så har sansynligvis hørt om Aslak Hellesøys Cucumber.

“Cucumber lets software development teams describe how software should behave in plain text. The text is written in a business-readable domain-specific language and serves as documentation, automated tests and development-aid - all rolled into one format.

“Cucumber works with Ruby, Java, .NET, Flex or web applications written in any language. It has been translated to over 30 spoken languages.

Men du har kanskje ikke testet det selv? Jeg tenkte derfor jeg kunne gjøre en rask demonstrasjon ved å skrive en akseptansetest for tjenesten jeg lagde i blogpostene om en minimal http-server i .Net / Ruby. Normalt vil man selvsagt beskrive featurene først, og så implementere dem og bruke cucumber til å bevise at de fungerer, men for enkelhets skyld tester jeg her altså min eksisterende tjeneste. Det spiller forøvrig ingen rolle om jeg tester .Net-varianten eller Ruby-varianten – jeg vil la akseptansetesten aksessere tjenesten direkte over http, og da er jo grensesnittet uansett det samme.

Det første jeg må gjøre er å beskrive tjenesten i form av en feature med tilhørende scenarier. Virker dette litt gresk anbefaler jeg at du leser deg litt opp på Behaviour-Driven Development (BDD).

File: features\add_service.feature:
1 Feature: Add-service
2   In order to save cycles on client CPUs
3   As an IT manager
4   I want a central server that can add numbers
5
6   Scenario: Add a string of numbers
7     When I send 9,11,33,100 to the add service
8     Then the response should be “The answer is 153″
9
10   Scenario: Add a single number
11     When I send 1 to the add service
12     Then the response should be “The answer is 1″

Feature-filen er input til cucumber, som vil analysere stegene i scenariene og forsøke å eksekvere dem. Men foreløpig skjønner cucumber lite, så vi må skrive litt kode for å definere stegene.

File: features\add_service_steps.rb:
1 require open-uri
2 require spec/expectations
3
4 When /I send (.*) to the (.*) service/ do |argument, service|
5   open(http://127.0.0.1:4567/#{service}?#{argument}) do |response|
6     @data = response.read
7   end
8 end
9
10 Then /the response should be “([^\”]*)/ do |expected|
11   @data.should == expected
12 end

Sånn, det er alt som trengs. Jeg lager et “When I send X to the Y service”-steg som gjør en forespørsel til tjenesten min og sender de definerte argumentene. Cucumber tar seg av å bytte ut X og Y med argumentene og navnet på tjenesten. “Then the response should be Z”-steget gjør en assert mot det forventede svaret som er beskrevet i scenariene.

Legg merke til at det er to forskjellige DSL’er (domenespesifike språk) i bruk her – en ekstern DSL for å definere features, og en intern Ruby-DSL (intern som i “er gyldig ruby-kode) for å definere stegene.

Når jeg kjører cucumber nå får jeg følgende output:

C:\Users\tormar\ruby_projects\httpListener>cucumber
Feature: Add-service
        In order to save cycles on client CPUs
        As an IT manager
        I want a central server that can add numbers

  Scenario: Add a string of numbers
    When I send 9,11,33,100 to the add service
    Then the response should be “The answer is 153

  Scenario: Add a single number
    When I send 1 to the add service
    Then the response should be “The answer is 1

2 scenarios (2 passed)
4 steps (4 passed)
0m0.122s

Alle scenariene for Add-servicen passerte (hvis ikke hadde det dukket opp endel rødt i output). Kult?

Hvis du er alergisk mot Ruby så finnes det også et prosjekt som heter SpecFlow som er en port av cucumber til .Net. Men det er absolutt å anbefale å benytte the real thing, gjerne med IronRuby på .Net-plattformen.

Å jobbe effektivt med drittkode

Onion architecture

Validering kan være et domene-ansvar

TDD og mocking i praksis

Avhengighetsisolering (a.k.a. Mocking) i .NET

Utenfra-og-inn programmering

Ultra-tiny given-when-then DSL-snippet

Systemer som blogger

Enhetstesting av konsoll-applikasjoner

Torbjørn Marø

Torbjørn er systemutvikler og et aktivt medlem av .NET-miljøet i Bergen. Dette er hans blog.

Siste kommentarer


Torbjørn: Skulle forresten ikke forundre meg om IronRuby - slik som mi...

Torbjørn: Er faktisk litt forvirret over de ulike strategiene man kan...

Jonas Follesø: Tips er og å se hvordan man lytter på events i IronRuby, s...

Torbjørn: Jeg unnlot med vilje å nevne ruby's implementasjon av Obser...

Odd Rune: Foretrekker ofte å bruke Observer jeg - http://ruby-doc.org...

Torbjørn: Takk for linken - gir god mening! Kanskje PSWinCom burde ha...

Bård Strøm: Ja, jeg er på. Interessante betraktninger når jeg nå skal...