behatAan de slag met behat


Opmerkingen

Deze sectie geeft een overzicht van wat gedrag is en waarom een ontwikkelaar het misschien wil gebruiken.

Het moet ook alle grote onderwerpen binnen behat vermelden en een link naar de gerelateerde onderwerpen bevatten. Aangezien de documentatie voor behat nieuw is, moet u mogelijk eerste versies van die gerelateerde onderwerpen maken.

Begin met Behat

Behat biedt Gherkin Syntax , een voor mensen leesbaar formaat. Hiermee kunt u eenvoudig uw gebruikersverhalen beschrijven.

Om met Behat te beginnen, moet u het installeren met Composer en vervolgens uw testbestanden initialiseren:

$ composer require --dev behat/behat="^3.0.5"

$ ./vendor/bin/behat --init

+d features # place your *.feature files here
+d features/bootstrap # place your context classes here
+f features/bootstrap/FeatureContext.php # place your definitions, transformations and hooks here
 

Standaard plaatst u uw testbestanden in de features/ map en heeft u de extensie .feature .

Elk testbestand moet een bepaald kenmerk van de toepassing definiëren. Een functie is onderverdeeld in een aantal scenario's en bevat een reeks stappen die met succes moeten worden uitgevoerd om het scenario te laten slagen. Elk scenario moet slagen om een functie te laten slagen.

# features/PartyHarmony.feature
Feature: Party Harmony
    As a Dungeon Master, I want to ensure harmony and mutual trust, so that
    the party can work together as a team

    Scenario: Teach members to respect each others property
        Given that the Wizard has 10 cookies
        And the Bard eats 1 cookie
        Then the Bard is mysteriously on fire
 

Om uw tests uit te voeren, voert u de Behat-binary rechtstreeks uit. We kunnen optioneel opgeven welk functiebestand moet worden uitgevoerd (anders worden alle tests uitgevoerd). Dit functiebestand zal mislukken met ongedefinieerde stappenfouten (omdat we niet hebben gedefinieerd wat die stappen betekenen):

$ ./vendor/bin/behat features/PartyHarmony.feature
Feature: Party Harmony
    As a Dungeon Master, I want to ensure harmony and mutual trust, so that
    the party can work together as a team

  Scenario: Teach members to respect each others property # features/PartyHarmony.feature:6
    Given that the Wizard has 10 cookies
    And the Bard eats 1 cookie
    Then the Bard is mysteriously on fire

1 scenario (1 undefined)
3 steps (3 undefined)
0m0.01s (10.49Mb)

--- FeatureContext has missing steps. Define them with these snippets:

    /**
     * @Given that the Wizard has :arg1 cookies
     */
    public function thatTheWizardHasCookies($arg1)
    {
        throw new PendingException();
    }

    /**
     * @Given the Bard eats :arg1 cookie
     */
    public function theBardEatsCookie($arg1)
    {
        throw new PendingException();
    }

    /**
     * @Then the Bard is mysteriously on fire
     */
    public function theBardIsMysteriouslyOnFire()
    {
        throw new PendingException();
    }
 

Elke stap in een scenario voert een stuk code uit een context PHP-bestand uit (verschillende functietests kunnen verschillende contexten laden). We kunnen de door Behat voorgestelde voorbeelden kopiëren of onze eigen voorbeelden maken. De stap wordt gekoppeld aan een reguliere expressiecontrole. Dus als we implementeren

<?php
# 
class FeatureContext {
    /**
     * @Given that the wizard has :num cookies
     */
    public function wizardHasCookies($num) {
        // $this->wizard is a pre-existing condition.... like syphilis
        $this->wizard->setNumberOfCookies($num);
    }

    /**
     * @Given the Bard eats :num cookie
     */
    public function theBardEatsCookie($num)
    {
        $this->bard->consumeCookies($num);
    }

    /**
     * @Then the Bard is mysteriously on fire
     */
    public function theBardIsMysteriouslyOnFire() {
        PHPUnit_Framework_Assert::assertTrue(
            $this->bard->isBardOnFire()
        );
    }
}
 

U zult het gebruik van PHPUnit_Framework_Assert . Behat heeft geen eigen assert-systeem, dus je kunt het systeem gebruiken dat je maar wilt.

Het uitvoeren van de tests zal nu de daadwerkelijke code uitvoeren en we kunnen testen of alles slaagt:

$ ./vendor/bin/behat features/PartyHarmony.feature
Feature: Party Harmony
    As a Dungeon Master, I want to ensure harmony and mutual trust, so that
    the party can work together as a team

  Scenario: Teach members to respect each others property # features/PartyHarmony.feature:6
    Given that the Wizard has 10 cookies                  # FeatureContext::thatTheWizardHasCookies()
    And the Bard eats 1 cookie                            # FeatureContext::theBardEatsCookie()
    Then the Bard is mysteriously on fire                 # FeatureContext::theBardIsMysteriouslyOnFire()

1 scenario (1 passed)
3 steps (3 passed)
0m0.01s (10.59Mb)
 

E-mails vastleggen

Functioneel testen kan ook testprocessen omvatten die uw omgeving verlaten, zoals externe API-aanroepen en e-mails.

Stel u bijvoorbeeld voor dat u het registratieproces voor uw website functioneel test. De laatste stap van dit proces omvat het verzenden van een e-mail met een activeringslink. Totdat deze link is bezocht, is het account niet volledig geregistreerd. U wilt beide testen:

  1. Dat de e-mail correct wordt verzonden (opmaak, vervanging van tijdelijke aanduiding, enz.) En,
  2. Dat de activeringslink werkt

Nu kunt u het verzenden van e-mail testen, maar een IMAP- of POP-client gebruiken om de verzonden e-mail uit de mailbox op te halen, maar dit betekent dat u ook uw internetverbinding, de externe e-mailserver en eventuele problemen bij de levering test (spamdetectie bijvoorbeeld).

Een eenvoudigere oplossing is om een lokale service te gebruiken die uitgaande SMTP-verbindingen vangt en de verzonden e-mail naar schijf dumpt.

Een paar voorbeelden zijn:

smtp-sink - Een hulpprogramma dat wordt meegeleverd met Postfix.

# Stop the currently running service
sudo service postfix stop

# Dumps outgoing emails to file as "day.hour.minute.second"
smtp-sink -d "%d.%H.%M.%S" localhost:2500 1000

# Now send mails to your local SMTP server as normal and they will be
# dumped to raw text file for you to open and read

# Run your functional tests
vendor/bin/behat
 

Vergeet niet om smtp-sink te doden en daarna je postfix-service te herstarten:

# Restart postfix
sudo service postfix start
 

FakeSMTP - Een op Java gebaseerde client die uitgaande e-mail vangt

# -b = Start without GUI interface
# -o = Which directory to dump your emails to
$ java -jar fakeSMTP.jar -b -o output_directory_name
 

Als alternatief kunt u een externe service gebruiken die deze service biedt, zoals mailtrap, maar uw tests zijn afhankelijk van internettoegang.

Behat uitbreiden met nerts

Mink biedt een interface voor MinkContext (zoals Goutte en Selenium) en een MinkContext die, indien uitgebreid, extra MinkContext biedt voor onze stappen.

Mink installeren (en het standaard Goutte-stuurprogramma):

$ composer require --dev behat/mink-extension="^2.0"
$ composer require --dev behat/mink-goutte-driver="^1.0"
 

MinkContext vervolgens uw context uit met MinkContext :

<?php
use Behat\MinkExtension\Context\MinkContext;

class FeatureContext extends MinkContext … {
    …
}
 

U kunt de volledige lijst met beschikbare syntaxis in uw Behat-installatie bekijken met de volgende opdracht:

$ ./vendor/bin/behat -dl

Given /^(?:|I )am on "(?P<page>[^"]+)"$/
 When /^(?:|I )reload the page$/
 When /^(?:|I )move backward one page$/
 When /^(?:|I )move forward one page$/
 When /^(?:|I )press "(?P<button>(?:[^"]|\\")*)"$/
 When /^(?:|I )follow "(?P<link>(?:[^"]|\\")*)"$/
 When /^(?:|I )fill in "(?P<field>(?:[^"]|\\")*)" with "(?P<value>(?:[^"]|\\")*)"$/
 

U moet vervolgens Mink configureren om aan te geven waar de website die u wilt testen zich bevindt en welke webdrivers u moet gebruiken (standaard Goutte):

# ./behat.yml
default:
    extensions:
        Behat\MinkExtension:
            base_url: "[your website URL]"
            sessions:
                default:
                    goutte: ~
 

Hier is een voorbeeld van een scenario met alleen de door Mink geleverde stappen:

# ./features/Authentication.feature
Feature: Authentication
    As a security conscious developer I wish to ensure that only valid users can access our website.

    Scenario: Login in successfully to my website
        When I am on "/login"
        And I fill in "email" with "my@email.com"
        And I fill in "password" with "my_password"
        And I press "Login"
        Then I should see "Successfully logged in"

    Scenario: Attempt to login with invalid credentials
        When I am on "/login"
        And I fill in "email" with "my@email.com"
        And I fill in "password" with "not_my_password"
        And I press "Login"
        Then I should see "Login failed"
 

Je kunt dit nu testen door de functie via Behat uit te voeren:

./vendor/bin/behat features/Authentication.feature
 

U kunt uw eigen stappen maken met MinkContext voor veelgebruikte stappen (inloggen is bijvoorbeeld een veel voorkomende bewerking):

Feature: Authentication
    As a security conscious developer I wish to ensure that only valid users can access our website.

    Scenario: Login in successfully to my website
        Given I login as "my@email.com" with password "my_password"
        Then I should see "Successfully logged in"

    Scenario: Attempt to login with invalid credentials
        Given I login as "my@email.com" with password "not_my_password"
        Then I should see "Login failed"
 

U moet uw contextbestand uitbreiden met de MinkContext om toegang te krijgen tot de MinkContext 's en pagina-interacties:

<?php
use Behat\MinkExtension\Context\MinkContext;

class FeatureContext extends MinkContext {
    /**
      * @Given I login as :username with password :password
      */
    public function iLoginAsWithPassword($username, $password) {
        $this->visit("/login");
        $this->fillField("email", $username);
        $this->fillField("password", $password);
        $this->pressButton("Login");
    }
}
 

Mink biedt ook CSS-selectors in de meeste vooraf opgegeven aanroepen waarmee u elementen op de pagina kunt identificeren met constructies zoals deze:

When I click on "div[id^='some-name']"
And I click on ".some-class:first"
And I click on "//html/body/table/thead/tr/th[first()]"
 

Functioneel testen als gebruikersverhalen

Functionele tests kunnen het beste worden beschreven als tests voor uw gebruikersverhalen. Als je eerder gebruikersverhalen hebt behandeld, volgen ze normaal gesproken het volgende patroon:

As a [role], I want to [desire], so that [benefit/desired outcome]
 

Voor de volgende voorbeelden zullen we dit gebruikersverhaal als voorbeeld gebruiken:

As a Dungeon Master, I want to ensure harmony and mutual trust, so that
the party can work together as a team
 

De twee populairste testkaders voor functionele tests in PHP zijn Behat en PHPSpec .

Installatie of instellingen

Behat / Mink

Installeren met behulp van componist (voor andere methoden controleren) behat.org Als je Linux gebruikt, zorg er dan voor dat je php-curl hebt geïnstalleerd (normale curl-installatie werkt niet)

Linux

sudo apt-get install php5-curl
 

Als u Windows gebruikt , zorg er dan voor dat PHP, Curl en Git zijn geïnstalleerd. U kunt deze vinden onder de volgende links:

Uw componist.json zou het volgende bevatten:

behat - componist.json

{
  "require": {
    "behat/behat": "dev-master",
    "behat/mink": "dev-master",
    "behat/mink-extension": "dev-master",
    "behat/mink-selenium2-driver": "dev-master",
    "phpunit/php-code-coverage": "dev-master",
    "phpunit/phpunit-mock-objects": "dev-master",
    "phpunit/phpunit": "dev-master"
  },
  "minimum-stability": "dev",
  "config": {
    "bin-dir": "bin/"
  }
}
 

(wanneer u het bestand composer.json in Windows opslaat, moet u "Alle bestanden" als bestandstype en "ANSI" -codering kiezen)

Voer daarna de volgende opdrachten uit:

$ curl http://getcomposer.org/installer | php
$ php composer.phar install
 

Nadat deze Behat-, Mink- en Behat-Mink-extensie zijn geïnstalleerd, wordt Beat uitgevoerd

gedrag uitvoeren

$ bin/behat
 

Gebruik om de Behat-Mink-extensie te activeren: behat.yml maak een bestand "behat.yml" met de volgende inhoud

behat.yml

default:
  suites:
    default:
      paths:
        features: %paths.base%/features/
        bootstrap: %paths.base%/features/bootstrap/
      contexts: 
        - FeatureContext
  extensions:
    Behat\MinkExtension:
      base_url: 'http://www.startTestUrl.de'
      selenium2:
        browser: firefox
        wd_host: "http://localhost:4444/wd/hub"
 

Dit bestand bevindt zich in dezelfde map die de bin-map en de te koppelen koppeling bevat.
Merk ook op dat in het yml-bestand geen tabbladen worden gebruikt voor inspringen. gebruik spaties. Gebruik om een lijst met beschikbare opdrachten in behat-mink te krijgen

$ bin/behat -di
 

Maak behat onderdeel van uw systeem

Linux

Ga naar uw homedirectory en doe het volgende:

$ sudo vi .bashrc
 

En voeg deze regels toe aan het einde van de map

export BEHAT_HOME=/home/*user*/path/to/behat
export PATH=$BEHAT_HOME/bin:$PATH
 

Start de console opnieuw of typ "source .bashrc"

ramen

Ga over de systeeminstellingen en voeg het pad van behat / bin toe aan de omgevingsvariabelen

Andere stuurprogramma's Over stuurprogramma's zoals Selenium, phantomjs, goutte, enz. Moeten ook worden geïnstalleerd.

Testgegevens instellen

Met functionele testen worden gegevens vaak aangepast. Hierdoor kunnen opeenvolgende runs van het testpakket mislukken (omdat de gegevens mogelijk zijn gewijzigd in de oorspronkelijke staat waarin ze zich bevonden).

Als u uw gegevensbron hebt ingesteld met behulp van een ORM of framework dat migratie of seeding ondersteunt (zoals Doctrine , Propel , Laravel ), kunt u dit gebruiken om een nieuwe testdatabase te maken compleet met Fixture-gegevens bij elke testrun.

Als u momenteel geen van deze (of gelijkwaardig) gebruikt, kunt u tools zoals Phinx gebruiken om snel een nieuwe testdatabase op te zetten of een bestaande database voor elke testrun voor te bereiden (testitems opschonen, gegevens terugzetten naar de oorspronkelijke staat) ).

# Install Phinx in your project
$ php composer.phar require robmorgan/phinx

$ php vendor/bin/phinx init
Phinx by Rob Morgan - https://phinx.org. version x.x.x
Created ./phinx.xml
 

Voeg uw database-inloggegevens toe aan ./phinx.xml .

$ php vendor/bin/phinx create InitialMigration
 

U kunt opgeven hoe uw databasetabellen worden gemaakt en gevuld met behulp van de syntaxis in de documentatie .

Vervolgens voert u elke keer dat u uw tests uitvoert een script als volgt uit:

#!/usr/bin/env bash

# Define the test database you'll use
DATABASE="test-database"

# Clean up and re-create this database and its contents
mysql -e "DROP DATABASE IF EXISTS $DATABASE"
mysql -e "CREATE DATABASE $DATABASE"
vendor/bin/phinx migrate

# Start your application using the test database (passed as an environment variable)
# You can access the value with $_ENV['database']
database=$DATABASE php -d variables_order=EGPCS -S localhost:8080

# Run your functional tests
vendor/bin/behat
 

Nu mogen uw functionele tests niet mislukken vanwege gegevenswijzigingen.

JavaScript testen met Mink en Selenium

Als we JavaScript op een website willen testen, moeten we iets krachtigers gebruiken dan Goutte (wat gewoon cURL is via Guzzle). Er zijn een aantal opties zoals ZombieJS , Selenium en Sahi . Voor dit voorbeeld zal ik Selenium gebruiken.

Eerst moet u de stuurprogramma's voor Mink installeren:

$ composer require --dev behat/mink-selenium2-driver="^1.2"
 

En je moet ook het stand-alone server jar-bestand van Selenium downloaden en het starten:

$ java -jar selenium-server-standalone-2.*.jar
 

We moeten Behat ook vertellen dat wanneer we de @javascript tag gebruiken om het Selenium-stuurprogramma te gebruiken en de locatie van de Selenium-standalone server @javascript .

# ./behat.yml
default:
    # …
    extensions:
        Behat\MinkExtension:
        base_url: "[your website URL]"
        sessions:
            # …
            javascript:
                selenium2:
                    browser: "firefox"
                    wd_host: http://localhost:4444/wd/hub
 

Vervolgens moet u voor elke test die u wilt uitvoeren met behulp van browseremulatie een @javascript (of @selenium2 ) tag toevoegen aan het begin van de functie of het scenario.

# ./features/TestSomeJavascriptThing.feature
@javascript # or we could use @selenium2
Feature: This test will be run with browser emulation
 

De test kan vervolgens worden uitgevoerd via Behat (zoals elke andere test). Het enige verschil is dat wanneer de test wordt uitgevoerd, er een browservenster op de computer wordt weergegeven waarop de zelfstandige server van Selenium wordt uitgevoerd, die vervolgens de beschreven tests uitvoert.