Refactoring using Codeception
-
Upload
jeroen-van-dijk -
Category
Technology
-
view
542 -
download
0
description
Transcript of Refactoring using Codeception
REFACTORING USING CODECEPTION
$I->CANSEE(‘JEROEN’, ‘#VANDIJK’)
$I->USETWITTER(‘@JRVANDIJK’)
$I->AM(‘PHPBNL’, ‘.BOARD-MEMBER’)
$I->WORK(‘#ENRISE’)
NETHERLANDS
UNITED KINGDOM
BELGIUM
GERMANY
AMSTERDAM
NETHERLANDS
UNITED KINGDOM
BELGIUM
GERMANY
AMSTERDAM
NOT AMSTERDAM
NETHERLANDS
UNITED KINGDOM
BELGIUM
GERMANY
AMERSFOORT
GRAIN WAREHOUSE
REFACTORED
THIS TALK IS NOT…
THIS TALK IS NOT…
DEPENDENCY INJECTION, DECOUPLING, ENCAPSULATION, TESTABLE CODE
REFACTORING
A SIMPLE BDD STYLE TESTING FRAMEWORK WHICH IS EASY TO READ, WRITE AND DEBUG
WHAT IS CODECEPTION?
YOU WRITE IN YOUR FAVORITE EDITOR
VENDOR/BIN/CODECEPT BOOTSTRAP
COMPOSER INSTALL CODECEPTION/CODECEPTION
class_name: AcceptanceTester modules: enabled: - PhpBrowser - AcceptanceHelper config: PhpBrowser: url: 'http://www.zendcon.com/'
ACCEPTANCE.SUITE.YML
PAGE USED FOR TESTING
public function seeIfNameExists(\AcceptanceTester $I) { $I->wantTo('see if conference name exists'); $I->amOnPage(‘/'); $I->click(‘#rt-logo‘); $I->see('zendcon'); }
CODECEPT GENERATE:CEST ACCEPTANCE HOME
STEPS
GENERATED FILE EXTENDS ACCEPTANCETESTER CLASS
CODECEPT GENERATE:STEPOBJECT ACCEPTANCE <NAME>
class CompareSteps extends \AcceptanceTester { public function seeIfNameExists() { $I = $this; $I->amOnPage('/'); $I->see('zendcon'); } }
class MenuCest { public function seeIfNameExistsViaCCStep(\CompareSteps $I) { $I->seeIfNameExists(); } }
REUSE CODE FOR DIFFERENT TESTS
PAGE OBJECTS
GENERATED FILE IS JUST A CONTAINER
CODECEPT GENERATE:PAGEOBJECT ACCEPTANCE <NAME>
class HomePage { public static $URL = '/'; … // removed code for slide layout purposes public static function of(AcceptanceTester $I) { return new static($I); }
public function see($value) { $I = $this->acceptanceTester; $I->amOnPage(self::$URL); $I->see($value); } }
PAGE OBJECT CONTAINER
public function seeIfNameExistsViaPageObject() { HomePage::of($this)->see('zendcon'); }
USE THE OBJECT IN A TEST
VERSION COMPARISON
FROM A TECHNICAL PERSPECTIVE
MASTER !== RELEASE/NEXTGEN
FROM A FUNCTIONAL PERSPECTIVE
MASTER === RELEASE/NEXTGEN
LOST OF CODE COMING UP…
ATTENTION PLEASE
public function getHtmlFromContent(InnerBrowser $innerBrowser, $css) { $crawler = $this->getCrawler($innerBrowser); $selector = CssSelector::toXPath($css); $value = $crawler->filterXPath($selector); return $value->html(); }
protected function getCrawler(InnerBrowser $innerBrowser) { $reflection = new \ReflectionClass(get_class($innerBrowser)); $property = $reflection->getProperty('crawler'); $property->setAccessible(true); return $property->getValue($innerBrowser); }
OVERRIDE DEFAULT CRAWLER
protected function getPhpBrowserByPage($page) { $phpBrowser = $this->getAlternatePhpBrowser(); $phpBrowser->amOnPage($page); return $phpBrowser; }
protected function getAlternatePhpBrowser() { $config = Configuration::config(); $suite = Configuration::suiteSettings('acceptance', $config); $options = $suite['modules']['config']['PhpBrowser']; $options['url'] = $options['alternate-url']; $phpBrowser = new PhpBrowser($options)->_initialize(); $this->setProxyInGuzzle($phpBrowser->guzzle); return $phpBrowser; }
CREATE SECOND PHPBROWSER INSTANCE
public function getHtml($page, $path) { $I = $this; $I->amOnPage($page); return $this->getHtmlFromContent( $I->fetchModule('PhpBrowser'), $path); }
public function getAlternateHtml($page, $path) { return $this->getHtmlFromContent( $this->getPhpBrowserByPage($page), $path); }
GET HTML OF BOTH VERSIONS
class_name: AcceptanceTester modules: enabled: - PhpBrowser - AcceptanceHelper config: PhpBrowser: url: 'http://www.zendcon.com/' alternate-url: 'http://zendcon.com'
ADDING ALTERNATE URL
public function seeSameOnVersions($page, $path, $altPath, $message) { $I = $this; list($left, $right) = $this->getContentFromVersions(
$page, $path, $altPath); $I->seeEquals($left, $right, $message); }
public function getContentFromVersions($page, $path, $altPath) { return array( $this->getHtml($page, $path), $this->getAlternateHtml($page, $altPath) ); }
COMPARING 2 VERSIONS IN 1 RUN
public function seeIfPageHeaderIsIdentical(\CompareSteps $I) { $I->seeSameOnVersions( \HomePage::$URL, 'h2', 'h2', 'Homepage header not identical' ); }
TEST PAGE HEADER
public function seeIfFormActionIsIdentical(\CompareSteps $I) { $I->seeSameOnVersions( \HomePage::$URL, '.rsformbox1', '.rsformbox1', 'Homepage signup form not identical' ); }
TEST SIGNUP FORM
public function seeIfFormActionIsIdentical(\CompareSteps $I) { $I->seeSameOnVersions( \HomePage::$URL, '.rsformbox1', '.rsformbox1', 'Homepage signup form not identical' ); }
<div class="rsformbox1 title3"> - <form method=“post" id="userForm" action="http://www.zendcon.com/"> + <form method="post" id="userForm" action="http://zendcon.com/">
TEST SIGNUP FORM
RUNNING THE TESTS!
EXAMPLES?
USER SPECIFIC SETTINGS
CODECEPTION.YML
VS
CODECEPTION.DIST.YML
CODECEPTION.YML.DIST
TESTING AN API
class_name: ApiTester modules: enabled: - ApiHelper - PhpBrowser - REST config: PhpBrowser: url: https://api.github.com REST: url: https://api.github.com
public function testGetGists(ApiTester $I) { $I->wantTo('see if we can get the gists listing'); $I->haveHttpHeader('Accept', 'application/vnd.github.beta+json'); $I->sendGet('/users/weierophinney/gists'); $I->seeResponseCodeIs(200); $I->seeResponseIsJson(); }
public function testGetGist(ApiTester $I) { $I->wantTo('see if we can get a gist'); $I->haveHttpHeader('Accept', 'application/vnd.github.beta+json'); $I->sendGet('/gists/2c47c9d59f4a5214f0c3'); $I->seeResponseCodeIs(200); $I->seeResponseIsJson(); }
ENVIRONMENTS
/** * @env beta */ public function testGetOldVersionGist(ApiTester $I) { $I->wantTo('see if we can get a gist'); $I->haveHttpHeader('Accept', $I->getAcceptHeader()); $I->sendGet('/gists/2c47c9d59f4a5214f0c3'); $I->seeResponseCodeIs(200); $I->seeResponseIsJson(); $I->seeResponseContainsJson( array('user' => array('login' => ‘weierophinney') )); }
/** * @env version3 */ public function testGetOldVersionGist(ApiTester $I) { $I->wantTo('see if we can get a gist'); $I->haveHttpHeader('Accept', $I->getAcceptHeader()); $I->sendGet('/gists/2c47c9d59f4a5214f0c3'); $I->seeResponseCodeIs(200); $I->seeResponseIsJson(); $I->seeResponseContainsJson( array('owner' => array('login' => ‘weierophinney') )); }
SPOT THE DIFFERENCE
env: beta: config: data: accept: application/vnd.github.beta+json version3: config: data: accept: application/vnd.github.v3+json
SUITE CONFIG ADDITIONS
TESTING 2 API VERSION IN 1 RUN
CODECEPT RUN API —ENV BETA —ENV VERSION3
EXAMPLES?
READY TO DIG DEEPER?
USING MODULES
USE YOUR IMAGINATION
CODECEPT GENERATE:SUITE
class MigrateHelper extends \Codeception\Module { public function seeIfLineExistsInFile($file, $line) { $filesystem = $this->getModule('Filesystem'); $filesystem->seeFileFound($file); $filesystem->seeInThisFile($line); } }
class HostCest { public function testIfHostsFileIsConfigured(MigrateTester $I) { $I->seeIfLineExistsInFile('/etc/hosts', '127.0.0.1'); } }
FILESYSTEM MODULE
class MigrateHelper extends \Codeception\Module { public function seeIfPortIsReachable($host, $port) { $cli = $this->getModule('Cli'); $cli->runShellCommand('nmap '.$host.' -Pn -p '.$port); $cli->seeInShellOutput($port.'/tcp open'); } }
class HostCest { public function testIfPortReachable(MigrateTester $I) { $I->seeIfPortIsReachable('www.zendcon.com', 80); } }
CLI MODULE
class MigrateHelper extends \Codeception\Module { public function seeAddressIsMatchingIp($address, $ip) { $cli = $this->getModule('Cli'); $cli->runShellCommand('host '.$address); $cli->seeInShellOutput($address . ' has address '.$ip); } }
class HostCest { public function testIfDnsCanBeResolved(MigrateTester $I) { $I->seeAddressIsMatchingIp('zendcon.com', '50.56.0.87'); } }
CLI MODULE
class MigrateHelper extends \Codeception\Module { public function seeContentsInRemoteFile($file, $line) { $server = $this->getModule('FTP'); $server->seeFileFound(basename($file), dirname($file)); $server->openFile($file); $server->seeInThisFile($line); } }
class HostCest { public function testIfRemoteFileHasContents(MigrateTester $I) { $I->seeContentsInRemoteFile('/etc/hosts', '127.0.0.1'); } }
FTP MODULE
FTP MODULE SIGNS IN BEFORE EVERY TEST
CAVEAT!
RUNNING THE TESTS!
GITHUB.COM/JVANDIJK/ZC14-CODECEPTION
JOIND.IN/11997