PFZ Workshop - Automatiseren van functionele tests

389 views

Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

PFZ Workshop - Automatiseren van functionele tests

  1. 1. WORKSHOPDAG 27 APRIL 2013Automatiseren van functionele tests met Behat en Mink&
  2. 2. VOORBEREIDING• Download en installeerVirtualbox (https://www.virtualbox.org/)• Download en installeerVagrant (http://www.vagrantup.com/)• https://github.com/pfznl/wsd13-functionaltesting/• $ git clone https://github.com/pfznl/wsd13-functionaltesting.git• $ cd wsd13-functionaltesting• $ vagrant up• ???• Profit
  3. 3. WAT HEB JE NODIG?• Computer/laptop• PHP 5.3• [Java] (als je selenium wilt draaien)• Virtualbox• [Vagrant]https://github.com/pfznl/wsd13-functionaltesting/
  4. 4. EVENVOORSTELLEN• @Richard_Tuin• Software ontwikkelaar• Speciale interesse in kwaliteit• Werkzaam bij Enrise
  5. 5. EN WIE ZIJN JULLIE?
  6. 6. HET PROBLEEM• Verschillend beeld op scope/werking van de oplevering• De klant weet soms achteraf pas hoe het systeem preciesgebruikt kan worden• “Het is wel mooi, maar zou x toch y kunnen werken?”• “Bedankt voor de nieuwe feature, maar nu werkt x niet meer”
  7. 7. HET PROBLEEM• Verschillend beeld op scope/werking van de oplevering• De klant weet soms achteraf pas hoe het systeem preciesgebruikt kan worden• “Het is wel mooi, maar zou x toch y kunnen werken?”• “Bedankt voor de nieuwe feature, maar nu werkt x niet meer”
  8. 8. WANT EIGENLIJK...• ... hebben we een gezamenlijk doel• ... willen we wat we gaan bouwen zo nauwkeurig mogelijkdefiniëren• ... willen we constante kwaliteit leveren
  9. 9. MAAR ER IS NOG EENPROBLEEM...
  10. 10. Developers zijn lui
  11. 11. DAT BETEKENT DAT...• ... we beter, en op gelijk niveau moeten communiceren• ... we een documentatiesysteem moeten bedenken voor deafstemming• ... we regelmatig moeten valideren dat wat we leveren nogvolgens specificaties is
  12. 12. DAT BETEKENT DAT...• ... we beter, en op gelijk niveau moeten communiceren• ... we een documentatiesysteem moeten bedenken voor deafstemming• ... we regelmatig moeten valideren dat wat we leveren nogvolgens specificaties isAutomatiseren?
  13. 13. SAMENWERKEN & DOCUMENTEREN
  14. 14. REGELMATIG (HER)VALIDERENVAN ACCEPTATIECRITERIADocumentatie
  15. 15. LATEN WE BIJ HET BEGINBEGINNEN...(dus nog even geen code)
  16. 16. KWALITEITWat is dat nou eigenlijk?
  17. 17. KWALITEIT=SOFTWARE DIE AAN DE EISENVOLDOET
  18. 18. HOE ZORG JE DANVOORKWALITEIT?
  19. 19. SAMENWERKEN &DOCUMENTEREN
  20. 20. ITERATIEFis het sleutelwoord
  21. 21. ITERATIEF“Stapsgewijs naar een optimum gaan.”
  22. 22. SOFTWAREONTWIKKELING
  23. 23. AGILE MANIFESTOMensen en hun onderlinge interactie > processen and toolsWerkende software > allesomvattende documentatieSamenwerking met de klant > contractonderhandelingenInspelen op verandering > het volgen van een plan
  24. 24. SAMENWERKEN ENDOCUMENTEREN
  25. 25. SAMENWERKEN ENDOCUMENTEREN1
  26. 26. SAMENWERKEN ENDOCUMENTEREN12
  27. 27. SAMENWERKEN ENDOCUMENTEREN123
  28. 28. OPSTELLENVAN REQUIREMENTS• Omschrijven hoe een probleem opgelost wordt• Gezamenlijk met de klant opstellen• In de taal (technische) van de klant• Functioneel gericht, niet technisch gericht
  29. 29. Ik wil graag een zoekmachine bouwen, zodatmijn bezoekers het hele internet kunnendoorzoeken!
  30. 30. Ik wil graag een zoekmachine bouwen, zodatmijn bezoekers het hele internet kunnendoorzoeken!Wow, leuke klus!Ik ga direct aan de slag
  31. 31. Alstublieft! Hier is de zoekmachine, mooi hè?
  32. 32. Alstublieft! Hier is de zoekmachine, mooi hè?Jawel, mooie foto op de achtergrond. Enhet zoeken werkt, maar ik bedoelde ookdat bezoekers op afbeeldingen kunnenzoeken!
  33. 33. Alstublieft! Hier is de zoekmachine, mooi hè?Jawel, mooie foto op de achtergrond. Enhet zoeken werkt, maar ik bedoelde ookdat bezoekers op afbeeldingen kunnenzoeken!Ja zeg, daar kom je nu mee
  34. 34. Alstublieft! Hier is de zoekmachine, mooi hè?Jawel, mooie foto op de achtergrond. Enhet zoeken werkt, maar ik bedoelde ookdat bezoekers op afbeeldingen kunnenzoeken!Ja zeg, daar kom je nu mee
  35. 35. SCHRIJF VOORBEELDEN!Ter ondersteuning van de communicatie
  36. 36. STAPPENPLAN1. Omschrijf de feature in één zin2. Omschrijf de intentie3. Schrijf realistische scenario’s
  37. 37. PRAKTIJKFeature: {feature omschrijving}{intentie}As a {personage(s)}I want {feature}So that {intentie}Scenario: {scenario omschrijving}Given {context}And {meer context}When {actie}Then {resultaat}Scenario: ...Informatie: http://dannorth.net/whats-in-a-story/
  38. 38. VOORBEELD ZOEKFUNCTIEFeature: Search on the internetAs a bing.com visitorI want to use the search engineSo that i can find information on the internetScenario: Simple keyword searchGiven I am on the homepageWhen I search the term “PHP”Then I should see search results containing “PHP”
  39. 39. LEVENDE DOCUMENTATIE• Alle features en scenario’s bij elkaar zijn de documentatie• Bij een change request werk je deze documentatie daarom bij
  40. 40. OVERWEGINGEN• Hoe gedetailleerd schrijf je de scenario’s?• Wie leest/schrijft de scenario’s?
  41. 41. COMMUNICATIE IS DE FOCUSAutomatiseren is maar bijzaak
  42. 42. Developers zijn lui
  43. 43. AUTOMATISERENKun je leren...
  44. 44. “A php framework for testing your business expectations.”
  45. 45. “Mink is an open source acceptance test framework for webapplications, written in PHP 5.3.”
  46. 46. +
  47. 47. +AWESOME
  48. 48. COMPONENTENVAN EEN FUNCTIONELETESTSUITE• Features• Feature parser• Browser controller client• Browser controller/simulator• Stappen programmeren met browser automatisering
  49. 49. COMPONENTENVAN EEN FUNCTIONELETESTSUITE• Features• Feature parser• Browser controller client• Browser controller/simulator• Stappen programmeren met browser automatiseringDocumentatie
  50. 50. COMPONENTENVAN EEN FUNCTIONELETESTSUITE• Features• Feature parser• Browser controller client• Browser controller/simulator• Stappen programmeren met browser automatiseringDocumentatieBehat
  51. 51. COMPONENTENVAN EEN FUNCTIONELETESTSUITE• Features• Feature parser• Browser controller client• Browser controller/simulator• Stappen programmeren met browser automatiseringDocumentatieBehatMink
  52. 52. COMPONENTENVAN EEN FUNCTIONELETESTSUITE• Features• Feature parser• Browser controller client• Browser controller/simulator• Stappen programmeren met browser automatiseringDocumentatieBehatMinkSelenium, Sahi, Goutte, etc.
  53. 53. COMPONENTENVAN EEN FUNCTIONELETESTSUITE• Features• Feature parser• Browser controller client• Browser controller/simulator• Stappen programmeren met browser automatiseringDocumentatieBehatMinkSelenium, Sahi, Goutte, etc.MinkExtension
  54. 54. COMPONENTEN OVERZICHT
  55. 55. TOYOUR BATTLESTATIONS!Tijd voor code
  56. 56. START DEVIRTUALBOX$ vagrant upOf importeer de OVAOf gebruik je lokale PHP installatie
  57. 57. INSTALLERENVAN BEHAT1. Maak een map genaamd “testsuite”2. Installeer composer (http://docs.behat.org/quick_intro.html#installation)3. Maak een bestand composer.json met de volgende inhoud:4. $ php composer.phar install{"require": {"behat/behat": "2.4.*@stable"},"minimum-stability": "dev","config": {"bin-dir": "bin/"}}$ curl http://getcomposer.org/installer | php
  58. 58. INSTALLERENVAN BEHAT1. Maak een map genaamd “testsuite”2. Installeer composer (http://docs.behat.org/quick_intro.html#installation)3. Maak een bestand composer.json met de volgende inhoud:4. $ php composer.phar install{"require": {"behat/behat": "2.4.*@stable"},"minimum-stability": "dev","config": {"bin-dir": "bin/"}}That’s it!$ curl http://getcomposer.org/installer | php
  59. 59. HELLO BEHAT1. Initialiseer een Behat testsuite met het commando:$ bin/behat --init2. Behat heeft de volgende mappen en bestanden aangemaakt:3. Run de testsuite: $ bin/behat
  60. 60. STEPS? (TERMINOLOGIE)Feature: {feature omschrijving}{intentie}As a {personage(s)}I want {feature}So that {intentie}Scenario: {scenario omschrijving}Given {context}And {meer context}When {actie}Then {resultaat}Scenario: ...
  61. 61. STEPS? (TERMINOLOGIE)Feature: {feature omschrijving}{intentie}As a {personage(s)}I want {feature}So that {intentie}Scenario: {scenario omschrijving}Given {context}And {meer context}When {actie}Then {resultaat}Scenario: ...Feature, user story, module
  62. 62. STEPS? (TERMINOLOGIE)Feature: {feature omschrijving}{intentie}As a {personage(s)}I want {feature}So that {intentie}Scenario: {scenario omschrijving}Given {context}And {meer context}When {actie}Then {resultaat}Scenario: ...Feature, user story, moduleScenario
  63. 63. STEPS? (TERMINOLOGIE)Feature: {feature omschrijving}{intentie}As a {personage(s)}I want {feature}So that {intentie}Scenario: {scenario omschrijving}Given {context}And {meer context}When {actie}Then {resultaat}Scenario: ...Feature, user story, moduleScenarioSteps
  64. 64. VOORBEELD FEATURE
  65. 65. UITBREIDING COMPOSER.JSON{"require": {"behat/behat": "2.4.*@stable","behat/mink-extension": "*","behat/mink": "*","behat/mink-selenium2-driver": "*","behat/mink-goutte-driver": "*","behat/mink-zombie-driver": "*","behat/mink-sahi-driver": "*"},"minimum-stability": "dev","config": {"bin-dir": "bin/"}}$ composer.phar update
  66. 66. VOORBEELD ZOEKFUNCTIEFeature: Search on the internetAs a bing.com visitorI want to use the search engineSo that i can find information on the internetScenario: Simple keyword searchGiven I am on the homepageWhen I search the term “PHP”Then I should see search results containing “PHP”features/search.feature
  67. 67. STEP DEFINITIES/*** @Given /^I am on the homepage$/*/public function iAmOnTheHomepage(){throw new PendingException();}/*** @When /^I search the term "([^"]*)"$/*/public function iSearchTheTerm($arg1){throw new PendingException();}Deze kun je in FeatureContext.php plaatsen, echter...
  68. 68. MINKEXTENSION1. Is een set van (basis) voorgedefinieerde steps2. Maakt gebruik van Mink3. Maar... niet alle teksten van de steps zijn even bruikbaar/*** Opens homepage.** @Given /^(?:|I )am on (?:|the )homepage$/* @When /^(?:|I )go to (?:|the )homepage$/*/public function iAmOnHomepage(){$this->getSession()->visit($this->locatePath(/));}
  69. 69. MINKTERMINOLOGIE• Driver = Browser controller/emulator• Session = Browser• Page = Document(Element)• Element• Selectors• XPath• CSS• Named
  70. 70. ./BEHAT.YMLdefault:extensions:BehatMinkExtensionExtension:default_session: gouttegoutte: ~base_url: "http://www.bing.com"context:parameters:foo: "bar"En dan....$ bin/behat
  71. 71. MINK STEPSGiven /^(?:|I )am on (?:|the )homepage$/When /^(?:|I )go to (?:|the )homepage$/Given /^(?:|I )am on "(?P<page>[^"]+)"$/When /^(?:|I )fill in "(?P<field>(?:[^"]|")*)" with "(?P<value>(?:[^"]|")*)"$/When /^(?:|I )press "(?P<button>(?:[^"]|")*)"$/When /^(?:|I )follow "(?P<link>(?:[^"]|")*)"$/Then /^(?:|I )should be on "(?P<page>[^"]+)"$/Then /^(?:|I )should see "(?P<text>(?:[^"]|")*)"$/$ bin/behat -dl/*** Clicks link with specified id|title|alt|text.** @When /^(?:|I )follow "(?P<link>(?:[^"]|")*)"$/*/public function clickLink($link){$link = $this->fixStepArgument($link);$this->getSession()->getPage()->clickLink($link);}
  72. 72. FEATURECONTEXT.PHP• Alles wat je in beginsel nodig hebt• De class voor je:• Step definitions• Hooks• Initialisatie
  73. 73. STEP DEFINITIES MAKEN/*** @When /^I search the term "([^"]*)"$/*/public function iSearchTheTerm($searchTerm){$this->fillField(q, $searchTerm); // Mink definities$this->pressButton(go);}/*** @When /^I search the term "([^"]*)"$/*/public function iSearchTheTerm($searchTerm){$page = $this->getSession()->getPage();$page->fillField(q, $searchTerm);$page->pressButton(go);}
  74. 74. UITKOMST
  75. 75. SELECTORS• Selecteren van elementen• XPath, CSS, Names$elements = $page->findAll(xpath, .//div[@class="sa_mc"]);$elements = $page->findAll(css, div[class="sa_mc"]);$elements = $page->findAll(named, array(link, Register);$elements = $page->findAll(named, array(button, Search);
  76. 76. DE LAATSTE STAPThen I should see search results containing “PHP”/*** @Then /^I should see search results containing (.*)$/*/public function iShouldSeeSearchResultsContaining($searchTerm){$searchTerm = quotemeta($searchTerm);$regex = sprintf(/%s/mi, $searchTerm);$page = $this->getSession()->getPage();$elements = $page->findAll(xpath, .//div[@class="sa_mc"]);foreach ($elements as $element) {if (!preg_match($regex, $element->getText())) {throw new Exception(One of the elements did not match the searchterm);}}}
  77. 77. PROFIELEN• Volledige configuratie per omgeving• Selectie op basis van filters• Te definieren in behat.yml:• Aan te roepen met: $ bin/behat --profile profielnaamdefault:extension:BehatMinkExtensionContextMinkContextbase_url: “http://www.example.org”profielnaam:extension:BehatMinkExtensionContextMinkContextbase_url: “http://acc.example.org”
  78. 78. TAGS• Handig om selectie te maken van features/scenario’s• Via command line: $ bin/behat --tags “@slow”• Definieer als filters in profile@smokeFeature: Search on the www@slowScenario: ...search.featureslowonly:filters:tags: “@slow”behat.ymlfast:filters:tags: “~@slow”behat.yml
  79. 79. FILTERS• Tests groeperen• Snel vs. traag• Tags• Configuratie in behat.ymlsmoketests:filters:tags: “@smoketest&&~@wip”development:filters:tags: “~@slow&&~@wip”
  80. 80. HOOKS• @beforeSuite• @beforeFeature• @beforeScenario• @beforeStep• @afterSuite• @afterFeature• @afterScenario• @afterStep
  81. 81. HOOKS/*** @afterScenario*/public function logoutUser(){$this->visit(/logout);}features/bootstrap/FeatureContext.php
  82. 82. BROWSER CONTROLLERSJavascript Snelheid OpmerkingGoutte Nee ++ EmulatorSelenium2 Ja -Sahi Ja ~Geen responsestatuscode, headers,authenticatieZombie.js Ja +
  83. 83. SCENARIO OUTLINESScenario Outline: Simple keyword searchGiven I am on the homepageWhen I search the term <searchterm>Then I should see search results containing <searchterm>Examples:| searchterm || PHP || Java || Pie || This string is possibly too long and uncommon |
  84. 84. DRIVER BENCHMARKGoutte 2.736msSelenium2 16.682msSahi ???Zombie.js 7.533ms20070 5,000 10,000 15,000 20,000Goutte Selenium Zombie.js
  85. 85. MULTILINEVARIABLESScenario:Given I input that spans several lines"""Test onetwo three"""/*** @Given /^I input that spans several lines$/*/public function iInputThatSpansSeveralLines(PyStringNode $string){(string) $string;$string->getRaw(); // string$string->getLines(); // array}
  86. 86. TABLESScenario:Given the following users are registered| name | password || Foo | test123 || Admin | secret |When I go to the user overviewThen I should see FooAnd I should see Admin/*** @Given /^the following users are registered$/*/public function theFollowingUsersAreRegistered(TableNode $table){foreach ($table->getHash() as $row) {// ... $row[name], $row[password]}}
  87. 87. LETTHERE BETESTING!
  88. 88. BEDANKT• Feedback: http://joind.in/talk/view/8566• Vragen?• @Richard_Tuin• richardtuin@gmail.com• skype: richardtuin

×