Browsed by
Author: Sander

Cucumber voor unit testing

Cucumber voor unit testing

Cucumber wordt vaak gebruikt voor webtesting (i.c.m. Selenium). Ik focus op Cucumber en puur Java en wil je laten zien waarom ik zo enthousiast ben over Cucumber voor unit testing.

Cucumber introductie

Cucumber is een framework voor Behavior Driven Development (BDD). Cucumber gebruikt gewone taal om specificaties vast te leggen. Vanuit die specificaties kun je eenvoudig code genereren die je helpt om testen voor specificaties te schrijven. Want TDD en BDD gaan prima samen! Voorbeeldje:

Feature: Simple math

  Scenario: Addition
    Given the number 1
    And we add 1
    When calculating
    Then the result should be 2

Leesbaar, zelfs voor je oma (en als ze geen Engels kan lezen, het kan ook volledig in het Nederlands!). Ik ga niet heel Cucumber uitleggen. Simpel gezegd:

  • Een feature (functionaliteit) is een verzameling van een of meer Scenarios
  • Een regel (feature step) begint met een keyword (Given, When, Then, …) en daarachter vrije tekst
  • Nummers en tekst tussen “quotes” worden automatisch herkend als testparameters

Voor dit voorbeeld heb je een simpel maven project nodig. Op de site van Cucumber zie je hoe je dit doet.
Sla het Feature/Scenario voorbeeld op in src/test/resources/bdd/math/math.feature.

Feature class

Deze feature willen we implementeren in een Java class. Maak in dit geval een Java class in src/test/java/math/MathFeature.java. Daar gaan we zometeen mee verder.

Test class

Om deze feature met JUnit testen te laten draaien, moeten we een Test Class maken met de annotations @RunWith en @CucumberOptions. Dit mag volgens Cucumber niet de feature class zijn (probeer maar eens, Cucumber geeft hier een zinnige foutmelding op). Ik vond het jammer om naast m’n feature class een lege class (file) te moeten maken met twee annotations, dus ik doe het met een inner class:

public class MathFeature {
    @RunWith(Cucumber.class)
    @CucumberOptions(features = "src/test/resources/bdd/math")
    public static class Runner {}
}

De feature class implementeren

Nu we een runner hebben, kunnen we de unit test eindelijk draaien! Doe dat voordat je de feature class gaat implementeren, want Cucumber helpt je hier enorm door in de output de code te plaatsen die je kunt copy/pasten naar de feature class!

public class MathFeature {
    @Given("^the number (\\d+)$")
    public void the_number(int number) throws Throwable {
    }

    @Given("^we add (\\d+)$")
    public void we_add(int number) throws Throwable {
    }

    @When("^calculating$")
    public void calculating() throws Throwable {
    }

    @Then("^the result should be (\\d+)$")
    public void the_result_should_be(int expectedResult) throws Throwable {
    }

    @RunWith(Cucumber.class)
    @CucumberOptions(features = "src/test/resources/bdd/sum")
    public static class Runner {
    }
}

Met dit skelet kun je de unit test verder in gaan vullen, dat valt buiten de scope van deze post.

Stapje verder

Met unit testen zie je vaak hetzelfde scenario met steeds nieuwe parameters. Je kunt natuurlijk het scenario meerdere keren copy/pasten en vullen met andere getallen. In Java zou je dat refactoren. JUnit heeft hiervoor parameterized tests.

In Cucumber kun je dit ook refactoren, namelijk met abstracte scenario’s:

  Scenario Template:
    Given the number <base>
    And we add <addition>
    Then the result should be <expected result>

    Examples:
      | base | addition | expected result |
      | 1    | 1        | 2               |
      | 2    | 2        | 4               |
      | 100  | 100      | 200             |

Het scenario bevat parameters tussen < en > en heeft een tabel met voor elke parameter een kolom. Elke regel is een afzonderlijke testgeval. Handig: Eclipse en IntelliJ hebben Cucumber plugins die zowel de teksten als de tabellen formatteren! Geen lamme spatiebalk-duim dus!

Mockito

Mockito is een veelgebruikt mocking framework. Als je in je feature class mocking annotations wilt gebruiken, dan moet je Mockito zelf initialiseren, omdat we de @RunWith al hebben gebruikt voor Cucumber:

public class OtherFeature {
    @InjectMocks
    private SuperService service;

    @Mock
    private SomeDependency dependency

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);
    }
}

Pas op! Je moet hier de @Before annotation uit cucumber.api.java gebruiken, niet uit org.junit!

Java 8

In Java 8 kun je je feature class ook anders implementeren. In dit voorbeeld kun je zien hoe je een step m.b.v. een lambda expressie maakt. Helaas zijn er wat problemen ontstaan met deze implementatie dus daar zullen we nog even op moeten wachten…

Waarom Cucumber unit tests?

Ik zie een aantal voordelen van de combinatie BDD/TDD/Unit tests:

  • TDD to the max! Je kunt beginnen zonder een regel code. Run tekst en schrijf (test)code tot je teKst slaagt.
  • Je unit tests worden gestructureerder. Je herstructureert en herbruikt zinsconstructies i.p.v. continue je code refactoren. Je testcode heeft dus meteen een betere structuur.
  • Iemand die jouw tests leest is er sneller in thuis.
  • Laat een ontwerper/tester zelf tests toevoegen om te kijken wat er gebeurt.

Met deze handvatten kun je een start maken met het schrijven van unit tests die voor iedereen leesbaar zijn. Natuurlijk geldt net als altijd: je hoeft niet al je unit tests op deze manier te schrijven. Begin er gewoon mee en laat me weten wat je er van vindt!

De ‘waaroms’ van AngularJS

De ‘waaroms’ van AngularJS

In de tutorials die ik heb gedaan hoorde ik vaak de uitspraak “Doe dit, anders gaat het fout.”. Wat is ‘dit’? Wat is ‘het’? Waarom gaat het ‘fout’? Ze denken iets uit te leggen en bij mij roept het vooral vragen op. Ik snap het niet. Waarom?

​Waarom ‘waarom’?​​​

​Waarom leren kinderen? Omdat ze bij alles vragen “Waarom?”. Zo leren ze de wereld om zich heen snappen.

‘Waarom’ is nog steeds een belangrijke vraag die naar mijn mening te weinig wordt gesteld. Natuurlijk is er de 5 Whys methode om een root cause analysis uit te voeren. Voor simpele dingen vraag je gewoon zelf ‘waarom’. Tenminste, dat zou je moeten. Ik doe dat wel. Ik wil de wereld om heen snappen.

AngularJS “waaroms”

Waarom heeft Google Angular bedacht?

Uiteraard heeft iedereen z’n eigen ideeën over deze ‘waarom’. Mobile support, data binding, sexy op je CV. Ik hoorde laatst een goeie opmerking waarom Google AngularJS heeft ontwikkeld:

Het businessmodel van Google is het leveren van diensten en het opslaan van data. Data is meestal ‘in ruste’. Hun diensten gonzen van bedrijvigheid. Wat nou als je daar op kunt besparen? Wat nou als we de rendering van pagina’s uitbesteden aan de clients en we geen dure servers hoeven te plaatsen om bijv. een JSF pagina te renderen? Tadaa! Google serveert data en je browser maakt er een mooi geheel van.

Waarom kan AngularJS niet tegen minification?

Javascript minification breekt de dependency injection van AngularJS. Deze code

    function myController($http) {}

kan worden geminified tot

    function a(b) {}

waardoor AngularJS geen $http meer kan herkennen en dus ook niet meer injecten.

De mooiste manier (vind ik) om dit te voorkomen is door $inject te gebruiken:

    myController.$inject = ['$http'];
    function myController($http) {}

De inhoud van strings wordt nooit geminified en AngularJS kan dus via de $inject achterhalen welke componenten er geïnject moeten worden:

    a.$inject = ['$http'];
    function a(b) {}

Waarom controllerAs?

De “controllerAs” syntax voorkomt dat je de binding variable $scope moet gebruiken. Je behandelt de controller als een object en niet als een factory die een ander object maakt.

    function myController() {
        var vm = this;
        vm.someList = [1, 2, 3];

Hierdoor is het ook mogelijk om controllers genest te gebruiken in je applicatie.

<div ng-controller="myController as c">
  <div ng-repeat="n in c.someList">
    <div ng-controller="otherController as o">
      <!-- now you can address both controllers as 'c' and 'o' -->
    </div>
  </div>
</div>

Waarom services én factories?

Dat vragen meer mensen zich af. Het idee voor nu is: gebruik services. Gelukkig zijn we straks van deze “waarom” af, want in Angular 2 bestaan beide concepten niet meer!

Canon P-150 (M) onder OS X Mavericks (10.9)

Canon P-150 (M) onder OS X Mavericks (10.9)

Sinds ik ben overgestapt op OS X 10.9 wil ‘m scanner (Canon P-150M) niet meer werken met andere apps, alleen maar met de meegeleverde CaptureOnTouch, die niet echt goed is… Ik heb Canon support lastig gevallen over de beschikbaarheid van 10.9 drivers, maar zij bleven maar zeggen dat de 10.8 drivers prima werken. Het probleem zit ‘m in de TWAIN driver. 3rd Party apps gebruiken TWAIN om met je scanner te praten en hier lijkt Mavericks roet in het eten te gooien.

Ik kwam deze post tegen van Jan Egil Vestbø waarin mijn probleem opgelost blijkt te zijn! De oplossing is eigenlijk heel simpel; vervang het kapotte deel van Mavericks met het goed werkende deel van Mountain Lion et voilá, m’n 3rd party app doet het weer!

Update OS X El Capitan: Helaas werkt deze fix niet meer in El Capitan.

Externe harde schijf niet automatisch mounten onder OS X

Externe harde schijf niet automatisch mounten onder OS X

Voor het repareren van een gecrashte harde schijf was ik op zoek naar een manier om te voorkomen dat OS X deze schijf automatisch zou mounten. Al Googlend kwam ik terecht op deze pagina met een command line hack. In de laatste zin vond ik wat ik zocht: Disk Arbitrator. Eenvoudiger kan bijna niet.

Let op: terwijl Disk Arbitrator actief was, kon Time Machine m’n netwerk backup volume niet openen…

Pimped my laptop

Pimped my laptop

Just pimped my laptop. Not that I didn’t like the looks of my MacBook Pro, but the laptop skins I found on http://glennz.com just struck me. At first they look like simple drawings, but if you look closer, it has a little story or gimmick to it.

This is the laptop skin I ordered from them and that is now hugging the back of my screen. Really looks beautifull!

It's a bottle, Jim

Read More Read More

Zuiver Communiceren

Zuiver Communiceren

Via Gewoon aan de slag volgde ik de cursus Zuiver Communiceren (ZC). Zuiver Communiceren is een manier van communiceren die onder andere gebruikt wordt bij coaching en advies.

In de IT zijn wij als techneuten vaak de partij die duidelijk moeten krijgen wat een klant wil. Vaak weet een klant dit zelf nog niet of ze hebben een ‘verkeerd’ idee. Zuiver Communiceren biedt je een aantal vragen en technieken waarmee je deze informatie eenvoudig kunt verkrijgen en verdiepen. Je zet hem/haar aan het denken en zelf luister en modelleer je alleen. Nadenken hoeft nauwelijks, dat leidt enkel tot aannames.
Ook kweek je begrip en vertrouwen door in de termen van de klant te praten (letterlijk herhalen), je leeft je in zijn wereld in. Je bereikt overeenstemming; weet dat je het over dezelfde zaken hebt, zonder aannames.

Read More Read More