behat Tutorial
Iniziare con behat
Ricerca…
Osservazioni
Questa sezione fornisce una panoramica di cosa sia, e perché uno sviluppatore potrebbe volerlo utilizzare.
Dovrebbe anche menzionare qualsiasi argomento di grandi dimensioni all'interno di behat e collegarsi agli argomenti correlati. Poiché la documentazione di behat è nuova, potrebbe essere necessario creare versioni iniziali di tali argomenti correlati.
Test funzionali come storie utente
I test funzionali sono meglio descritti come test per le tue storie utente. Se hai affrontato le storie degli utenti prima che normalmente seguano il seguente schema:
As a [role], I want to [desire], so that [benefit/desired outcome]
Per gli esempi seguenti utilizzeremo questa User story come esempio:
As a Dungeon Master, I want to ensure harmony and mutual trust, so that
the party can work together as a team
I due framework di test più popolari per i test funzionali in PHP sono Behat e PHPSpec .
Cominciando da Behat
Behat fornisce Gherkin Syntax che è un formato leggibile dall'uomo. Ti consente di descrivere facilmente le tue storie utente.
Per iniziare con Behat dovresti installarlo con Composer e quindi inizializzare i tuoi file di test:
$ 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
Per impostazione predefinita, i file di test vengono posizionati nella cartella .feature
features/
e hanno l'estensione .feature
.
Ogni file di test dovrebbe definire una particolare funzionalità dell'applicazione. Una funzionalità è suddivisa in una serie di scenari e contiene una serie di passaggi che devono essere eseguiti correttamente affinché lo scenario passi. Ogni scenario deve passare per passare una funzionalità.
# 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
Per eseguire i test, si esegue direttamente il binario Behat. Opzionalmente possiamo specificare quale file funzione eseguire (altrimenti vengono eseguiti tutti i test). Questo file funzione fallirà con errori di passi non definiti (perché non abbiamo definito cosa significano quei passaggi):
$ ./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();
}
Ogni fase di uno scenario esegue una parte di codice da un file PHP di contesto (diversi test di funzionalità possono caricare diversi contesti). Possiamo copiare gli esempi suggeriti da Behat o crearne di nostri. Il passo è abbinato ad un controllo di espressione regolare. Quindi se implementiamo
<?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()
);
}
}
Noterai l'uso di PHPUnit_Framework_Assert
. Behat non ha il proprio sistema di assert, quindi puoi usare quello che vuoi.
Ora eseguendo i test verrà eseguito il codice effettivo e possiamo verificare se tutto passa:
$ ./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)
Estendere Behat con Visone
Mink fornisce un'interfaccia per i driver web (come Goutte e Selenium) e un MinkContext
che, quando esteso, fornisce un linguaggio web aggiuntivo per i nostri passi.
Per installare Mink (e il driver Goutte predefinito):
$ composer require --dev behat/mink-extension="^2.0"
$ composer require --dev behat/mink-goutte-driver="^1.0"
Quindi estendi il tuo contesto con MinkContext
:
<?php
use Behat\MinkExtension\Context\MinkContext;
class FeatureContext extends MinkContext … {
…
}
È possibile visualizzare l'intero elenco di sintassi disponibile nell'installazione di Behat con il seguente comando:
$ ./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>(?:[^"]|\\")*)"$/
È quindi necessario configurare Visone per indicare dove si trova il sito Web che si desidera testare e quali driver Web utilizzare (Goutte per impostazione predefinita):
# ./behat.yml
default:
extensions:
Behat\MinkExtension:
base_url: "[your website URL]"
sessions:
default:
goutte: ~
Ecco un esempio di uno scenario che utilizza solo i passaggi forniti da Mink:
# ./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 "[email protected]"
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 "[email protected]"
And I fill in "password" with "not_my_password"
And I press "Login"
Then I should see "Login failed"
Ora puoi testarlo eseguendo la funzione tramite Behat:
./vendor/bin/behat features/Authentication.feature
È possibile creare i propri passi utilizzando MinkContext
per i passaggi comuni (ad esempio, il login è un'operazione molto comune):
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 "[email protected]" with password "my_password"
Then I should see "Successfully logged in"
Scenario: Attempt to login with invalid credentials
Given I login as "[email protected]" with password "not_my_password"
Then I should see "Login failed"
Sarà necessario estendere il file di contesto con MinkContext
per ottenere l'accesso ai driver Web e alle interazioni di pagina:
<?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 fornisce anche selettori CSS nella maggior parte delle chiamate pre-fornite che ti permettono di identificare gli elementi sulla pagina usando costrutti come questo:
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()]"
Test di JavaScript con Visone e Mink
Se vogliamo testare JavaScript su un sito web, avremo bisogno di usare qualcosa di un po 'più potente di Goutte (che è semplicemente cURL via Guzzle). Ci sono un paio di opzioni come ZombieJS , Selenium e Sahi . Per questo esempio userò il selenio.
Per prima cosa dovrai installare i driver per Mink:
$ composer require --dev behat/mink-selenium2-driver="^1.2"
E dovrai anche scaricare il file jar del server autonomo Selenium e avviarlo:
$ java -jar selenium-server-standalone-2.*.jar
Dovremo anche dirlo a Behat quando useremo il tag @javascript
per utilizzare il driver Selenium e fornire la posizione del server autonomo Selenium.
# ./behat.yml
default:
# …
extensions:
Behat\MinkExtension:
base_url: "[your website URL]"
sessions:
# …
javascript:
selenium2:
browser: "firefox"
wd_host: http://localhost:4444/wd/hub
Quindi, per ogni test che si desidera eseguire utilizzando l'emulazione del browser, è sufficiente aggiungere un @javascript
(o @selenium2
@javascript
) all'inizio della funzione o dello scenario.
# ./features/TestSomeJavascriptThing.feature
@javascript # or we could use @selenium2
Feature: This test will be run with browser emulation
Il test può quindi essere eseguito tramite Behat (come qualsiasi altro test). L'unica differenza è che, quando viene eseguito il test, dovrebbe generare una finestra del browser sul computer su cui è in esecuzione il server autonomo Selenium che eseguirà quindi i test descritti.
Impostazione dei dati di test
Con i dati di test funzionali viene spesso modificato. Ciò può causare il fallimento delle successive esecuzioni della suite di test (poiché i dati potrebbero essere cambiati rispetto allo stato originale in cui si trovava).
Se hai impostato la tua origine dati usando un ORM o un framework che supporti la migrazione o il seeding (come Doctrine , Propel , Laravel ), puoi usarlo per creare un nuovo database di test completo di dati Fixture su ciascuna esecuzione di test.
Se al momento non si utilizza uno di questi (o equivalente), è possibile utilizzare strumenti come Phinx per configurare rapidamente un nuovo database di test o preparare un database esistente per ciascuna esecuzione di test (pulire le voci di test, ripristinare i dati allo stato originale ).
# 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
Aggiungi le credenziali del tuo database a ./phinx.xml
.
$ php vendor/bin/phinx create InitialMigration
È possibile specificare come vengono create e popolate le tabelle del database utilizzando la sintassi fornita nella documentazione .
Quindi, ogni volta che esegui i test, esegui uno script come questo:
#!/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
Ora i tuoi test funzionali non dovrebbero fallire a causa delle modifiche ai dati.
Catturare e-mail
I test funzionali possono includere anche i processi di test che lasciano il vostro ambiente, come le chiamate API esterne e le e-mail.
Ad esempio, immagina di testare funzionalmente il processo di registrazione per il tuo sito web. Il passaggio finale di questo processo prevede l'invio di un'e-mail con un link di attivazione. Fino a quando questo collegamento non viene visitato, l'account non è completamente registrato. Vorresti testare entrambi:
- Che l'email verrà inviata correttamente (formattazione, sostituzione segnaposto, ecc.) E
- Che il link di attivazione funzioni
Ora è possibile testare l'invio di e-mail ma utilizzare un client IMAP o POP per recuperare l'e-mail inviata dalla casella di posta, ma significa anche testare la connessione Internet, il server e-mail remoto e eventuali problemi che potrebbero verificarsi nella consegna (rilevamento di spam per esempio).
Una soluzione più semplice consiste nell'utilizzare un servizio locale che intrappola le connessioni SMTP in uscita e scarica l'e-mail inviata su disco.
Un paio di esempi sono:
smtp-sink - Un programma di utilità fornito in bundle con 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
Non dimenticare di uccidere smtp-sink
e successivamente riavviare il servizio postfix:
# Restart postfix
sudo service postfix start
FakeSMTP - Un client basato su Java che intrappola la posta in uscita
# -b = Start without GUI interface
# -o = Which directory to dump your emails to
$ java -jar fakeSMTP.jar -b -o output_directory_name
In alternativa puoi utilizzare un servizio remoto che fornisce questo servizio come il servizio Mailtrap, ma il tuo test dipende dall'accesso a Internet.
Installazione o configurazione
Behat / Mink
Installa usando compositore (per altri metodi controlla) behat.org Se stai usando linux, assicurati di aver installato php-curl (l'installazione di curl normale non funzionerà)
Linux
sudo apt-get install php5-curl
Se stai usando Windows , assicurati di aver installato PHP, Curl e Git. Puoi trovare quelli sotto i seguenti link:
- PHP (Xampp): https://www.apachefriends.org/de/index.html
- Curl: http://curl.haxx.se/latest.cgi?curl=win64-nossl
- Git: http://git-scm.com/download/win
Il tuo compositore.json conterrà quanto segue:
behat - compositore.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/"
}
}
(quando si salva il file compositore.json in Windows, è necessario selezionare "Tutti i file" come Codetype e codifica "ANSI")
Successivamente esegui i seguenti comandi:
$ curl http://getcomposer.org/installer | php
$ php composer.phar install
Dopo questa installazione, vengono installati l'estensione Behat, Mink e Behat-Mink, per eseguire behat
esegui behat
$ bin/behat
Per attivare l'estensione Behat-Mink utilizzare: behat.yml creare un file "behat.yml" con il seguente contenuto
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"
Questo file si troverà nella stessa directory che contiene la directory bin e il collegamento a behat.
Si noti inoltre che nel file yml, non utilizzare le schede per il rientro. usa gli spazi. Per ottenere un elenco di comandi disponibili in behat-visone, utilizzare
$ bin/behat -di
Fai in modo che faccia parte del tuo sistema
Linux
Vai a Homedirectory e fai quanto segue:
$ sudo vi .bashrc
E aggiungi queste righe alla fine della directory
export BEHAT_HOME=/home/*user*/path/to/behat
export PATH=$BEHAT_HOME/bin:$PATH
Riavvia la console o digita "source .bashrc"
finestre
Vai oltre le Impostazioni di sistema e aggiungi il percorso di behat / bin alle variabili di ambiente
Altri driver Devono essere installati anche driver come Selenium, phantomjs, goutte, ecc.