Története és elvei
Aslak Hellesøy készítette az első 1.0.0 verziót ami 2012. június 20-án jelent meg. Maga az eszköz a Behavior-Driven Development (BDD) elveit követi
Ebben a tesztelési hozzáállásban az alapelvek:
- Előre írjuk meg a tesztet a komponensünkhöz
- Az elkészült tesztek után implementáljunk
- A tesztek sorozatos futtatásával finomítsuk a kódot
- A tesztek minden esetben megfogalmazhatóak, illetve specifikálhatóak természetes nyelven
Ruby nyelven íródott, de azon kívül is léteznek implementációk, ezekből néhány az eredetit használja és egyfajta hidat képez a célnyelv és a Cucumber között (pl. cuke4php és cuke4lua)
Weboldal:
http://cukes.info/
A BDD-nek megfelelően a tesztek két részből állnak:
- A megrendelő számára átadható informális leírás
- Az informális leírás sorainak megfelelő valódi program
Az informális leírás
Az informális leírásra a következő megkötések érvényesek:
- Egy .feature kiterjesztésű fájlba kell írni őket
- Beépített kulcsszavakat kell használni
- Feature, Scenario / Scenario outline és Examples
- Given, And, When, Then
- A kulcsszavak egyébként több nyelven is megadhatók nem csak angolul:
- Jellemző, Forgatókönyv /Forgatókönyv vázlat és Példák
- Amennyiben, És, Ha, Akkor
Példa: division.feature
# language: en
Feature: Division
In order to avoid silly mistakes
Cashiers must be able to calculate a fraction
Scenario: Regular numbers
Given I have entered 3 into the calculator
And I have entered 2 into the calculator
When I press divide
Then the result should be 1.5 on the screen
Példa: addition.feature
# language: en
Feature: Addition
In order to avoid silly mistakes
As a math idiot
I want to be told the sum of two numbers
Scenario Outline: Add two numbers
Given I have entered
into the calculator
And I have entered
into the calculator
When I press <button>
Then the result should be <output> on the screen
Examples:
| input_1 | input_2 | button | output |
| 20 | 30 | add | 50 |
| 2 | 5 | add | 7 |
| 0 | 40 | add | 40 |
A formális leírás (a teszt kódja)
Az informális leírások konkrét lépéseit (stepjeit) végrehajtó kódot pedig a step_definitions könyvtárba kell helyezni ami a feature fájllal egy szinten van.
A lépések kódjának keretét nem kell kézzel megírni azt a futtató rendszer kiírja amennyiben nem találja meg azokat. Az ebben lévő paramétereket pedig reguláris kifejezésekkel lehet kinyerni.
Példa: calculator_steps.rb
# encoding: utf-8
begin require 'rspec/expectations'; rescue LoadError; require 'spec/expectations'; end
require 'cucumber/formatter/unicode'
$:.unshift(File.dirname(__FILE__) + '/../../lib')
require 'calculator'
Before do
@calc = Calculator.new
end
After do end
Given /I have entered (\d+) into the calculator/ do |n|
@calc.push n.to_i
end
When /I press (\w+)/ do |op|
@result = @calc.send op
end
Then /the result should be (.*) on the screen/ do |result|
@result.should == result.to_f
end
A javasolt könyvtárstruktúra a következő:
features (Ide tesszük a .feature fájlokat)
|--- step_definitions (Ide tesszük a lépések definícióit)
|--- support (Az itt található forrásfájlok induláskor betöltődnek)
A tesztelés indítása alapesetben úgy történik, hogy egy terminálon belépünk a features könyvtárral egy szintre
és kiadjuk a cucumber parancsot. Ekkor az összes feature fájlt feldolgozza. Ezt a működést többféleképpen is felüldefiniálhatjuk:
- Megadhatjuk konkrétan a feature fájl nevét a parancs után
cucumber features/AwesomeFeature.feature
- Használhatunk Tag-eket, amelyekkel szeparálhatjuk a teszteseteinket.
Például csak adott taggel megjelölt teszteseteket futtathatunk.
A tagek arra valók, hogy a teszteseteinket csoportokba szervezzük azért, hogy ne kelljen minden esetben minden tesztet lefuttatni.
Tag-ek használata
@billing
Feature: Verify billing
@important
Scenario: Missing product description
Scenario: Several products
A teszt futtatása
Alap lehetőségek
Alapesetben a tesztek egyszerűen a
cucumber parancs kiadásával futtathatók a
features mappával egy szinten. Ekkor az összes tesztünk lefut és az eredményt a képernyőre írja.
Nem definiált lépések eredménye
Jó teszteset eredménye
Hibás teszteset eredménye
Tag-ek megadása futtatáskor
cucumber –-tags @billing
(Csak a @billing taggel jelöltek)
cucumber –-tags @important
(Csak az @important taggel jelöltek)
cucumber –-tags ~@important
(Minden ami nincs megjelölve @important taggel)
cucumber --tags @billing --tags @important
(Minden teszt lefut ami @billing ÉS @important)
cucumber --tags @billing,@important
(Minden teszt lefut ami @billing VAGY @important)
Webes tesztelés
Mivel már tudjuk, hogy hogyan lehet a Cucumbert használni ezért belevághatunk a WEB-es tesztelésbe is.
A hagyományos esetben Ruby osztályokat tesztelünk, de a weboldalak teszteléséhez komolyabb segítségre van szükségünk, hiszen a böngészővel való kommunikációt kell megoldanunk.
Tudnunk kell utasítani a böngészőt bizonyos dolgok végrehajtására és le kell tudnunk kérdezni tőle a teljes HTML DOM struktúrát, hogy megkaphassuk a számunkra szükséges adatokat.
Ehhez a Watir nevű Ruby gem-et használhatjuk. Ez képes a böngészőkkel kommunikálni. Használata egyszerű, az alapok elsajátítása után gyorsan lehet használni.
Alapvetően a tesztjeinkhez egy böngésző példányra van szükségünk. Ezt létrehozhatjuk a kódunkban (az env.rb fájlban) a következő kódrészlettel.
Watir browser létrehozása teszthez
begin require 'rspec/expectations'; rescue LoadError; require 'spec/expectations'; end
require 'watir-webdriver'
browser = Watir::Browser.new :ff
Before do
@browser = browser
end
# "after all"
at_exit do
browser.close
end
Itt lényegében megnyitjuk a böngészőnket a Before do … end részben pedig átadjuk majd a tesztlépéseinknek a böngészőt reprezentáló Ruby objektumot.
az at_exit do … end részben pedig a tesztek lefutása után bezárjuk a böngészőt.
Ezután már csak azt kell tudnunk, hogy hogyan is kommunikáljunk a megnyitott böngészőablakkal. Ehhez egyszerűen
használhatjuk a böngésző objektumot. A következőkben felsorolt metódusok listája természetesen nem teljes körű.
Alap lehetőségek a Watir browser objektumon
- browser.goto 'http://bit.ly/watir-example'
- A böngészőben a megadott címre navigál
-
browser.text_field(:name => 'entry.0.single').set 'Watir'
- A name attribútum alapján lekérdez egy szövegmezőt és az értékét a paraméterül kapottra állítja. Textarea esetén is ugyanez használatos, itt a sortörést nyugodtan beírhatjuk az értékbe.
-
browser.radio(:value => 'Watir').set
browser.radio(:value => 'Watir').clear
- Rádiógombokat állíthatunk be vagy törölhetjük a kijelölést.
- browser.checkbox(:value => 'Python').set
browser.checkbox(:value => 'Python').clear
- Checkboxok kezelését végezhetjük el hasonlóan a rádiógombokhoz.
-
browser.button(:name => 'logon').click
- „Rákattinthatunk” egy gombra.
-
browser.select_list(:name => 'list').clear
browser.select_list(:name => 'list').options
browser.select_list(:name => 'list').select 'Chrome'
- Legördülő listákat kezelhetünk. Az első törli a kijelölést, a második visszaadja a lehetőségeket, a harmadik pedig kijelöli az egyik elemet.
- browser.text.include? 'Your response has been recorded.'
- Megnézhetjük, hogy egy adott szöveg szerepel-e a legenerált oldalban. Nyilván az include? hívás nélkül megkapjuk az oldal szövegét.
- browser.title
- Az oldal címét kérdezhetjük le.
Hook-ok
Arra valók, hogy 1-1 adott végrehajtási egység előtt illetve után lefuttathassunk kódrészeket például a teszteset környezetének inicializálása érdekében vagy a teszteset utáni takarítás miatt.
A Watir browser létrehozásakor már láttunk erre példát.
Dokumentáció:
https://github.com/cucumber/cucumber/wiki/Hooks
Hook-ok fajtái
- Scenario hookok
- Minden Scenario/Scenario outline előtt/után fut. Az Around hook pedig a scenario-t
kapja paraméterül és az őt reprezentáló blokkot
- Before do |scenario| … end
- After do |scenario| … end
- Around('@fast') do |scenario, block| … end
- Step hook
- Minden Step után lefut
- AfterStep do |scenario| … end
- Configuration hook
- A konfigurációs beállításiok betöltése után fut le.
- AfterConfiguration do |config| … end
- Kilépési hook