.center.middle # Groovy BDD ## Smidig 2011 .footnote[Ole Christian Langfjæran Bekk Consulting] --- .center.middle # Behaviour # Driven # Development --- .center.middle # Given # When # Then --- .center.middle # Java --- .center.middle # Cucumber --- .center.middle # JBehave --- .center.middle # Cucumber --- .middle For eksempel Feature: Division In order to avoid silly mistakes Cashiers must be able to calculate a fraction Scenario: Regular numbers I have entered 3 into the calculator I press divide I have entered 2 into the calculator 1.5 on screen --- .center.middle ![Cucumber](images/cucumber.jpg) --- .center.middle # Groovy --- .middle ## Factories, factories, factories .java class ObjectFactory { static Ninja ninja(Map params = [:]){ return new Ninja([name:"Splinter", weapon:"Katana"]+params) } ... Ninja n = ninja(name:"Shredder"); --- .middle ## @Delegate .java class MyeBruktKode{ String someNumber() { return "42" } } class MinService{ @Delegate MyeBruktKode mye = new MyeBruktKode() String whatsTheMeaningOfLife() { return someNumber() } } --- .center.middle ![GroovyBDDFlow](images/groovybddflow.jpg) --- .middle ## Given, When, Then .java class AbstractGroovyFeature { @Autowired protected GodAndOdinStep Given = new GodAndOdinStep(); @Autowired protected GodAndOdinStep When = Given; @Autowired protected GodAndOdinStep Then = Given; @Autowired protected GodAndOdinStep And = Given; @Autowired protected RemoveEntity remove } --- .middle ## Many small steps .java @Component class GodAndOdinStep { @Delegate DateCalculatorSteps dateCalculatorSteps = new DateCalculatorSteps(); @Autowired @Delegate NinjaStep ninjaStep @Autowired @Delegate NinjaHouseStep ninjaHouseStep } --- .middle ## The Step .java class DateCalculatorSteps { DateCalculator calculator; String result void today_is(String date){ calculator = new DateCalculator(Date.parse("yyyy-MM-dd", date)) } void I_ask_if_the_date_is_in_the_past_for(String date){ result = calculator.isDateInThePast(Date.parse("yyyy-MM-dd", date)) } void the_result_from_the_datecalculator_should_be(String answer){ assertThat(result, equalTo(answer)) } } --- .middle ## The DateCalculator Feature .java class DateCalculatorFeature extends AbstractGroovyFeature{ @Test void determine_past_date(){ Given.today_is "2011-11-04" When.I_ask_if_the_date_is_in_the_past_for "2011-1-1" Then.the_result_from_the_datecalculator_should_be "yes" } } --- .center.middle # Spring # Hibernate --- .middle ## RunWith Spring like the wind .java @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations=["classpath:applicationContext-groovy-bdd.xml"]) class AbstractSpringGroovyFeature extends AbstractGroovyFeature { } --- .middle ## Groovy NinjaFeatures sprinkled with Spring .java class NinjaFeatures extends AbstractSpringGroovyFeature{ @Test void should_be_able_to_kill_a_ninja(){ Given.ninja_exists([name:"Shredder"]) When.the_ninja_gets_killed_by SHURIKIEN Then.the_ninja_should_be_dead "Shredder" } @After void clean_up_repo() { remove.allEntities(); } --- .middle ## Spring up for NinjaStep .java @Component class NinjaStep { @Autowired GetEntity get @Autowired PersistEntity persist private Ninja _ninja @Transactional void ninja_exists(Object theNinja = null) { _ninja = theNinja == null ? ninja() : new Ninja(theNinja) persist.entity(_ninja); } @Transactional void the_ninja_gets_killed_by(Weapon weapon) { get.ninja(_ninja.name).killBy(weapon); } @Transactional void the_ninja_should_be_dead(String nameOfNinja) { assertThat(get.ninja(nameOfNinja).isDead(), equalTo(true)); } } --- .middle ## Real life crisis .java @Test void skal_hente_en_ledig_boligperiode_naar_det_finnes_boliger() { Gitt.Gitt_at_vi_har_en_fresh_database(); Og.at_utleieenheten_eksisterer([enhetId: "BJE", active: true, names: [no: "Bjerke", en: "Bjerke"]]); Og.at_boligtypen_med_kode_og_navn_eksisterer("HM", "HM", "BJE"); Og.at_utleieobjekt_med_id_og_status_eksisterer("BJErkis007", "BJE", "HM", klarmeldt()); Naar.jeg_henter_boligperioder_tildelinger_med_filtrering_paa([tildelingsdato: JUN_1]) Saa.skal_jeg_faa_en_liste_med_ledige_boligperioder_som_har_lengde(1) Og.forste_ledige_boligperiode_ha_antall_ledige(1) } --- .center.middle # ? ## [bit.ly/GroovyBDD](http://bit.ly/GroovyBDD) .footnote[Laget med [github.com/gnab/remark](http://github.com/gnab/remark)] --- .center.middle # Cucumber JVM --- .middle ## JUnit .java @RunWith(Cucumber.class) @Feature(value = "date_calculator.feature") public class date_calculator_Test { } --- .center.middle ![JUnit Cucumber](images/junit_cucumber.png)