Transcript
Page 1: Refactoring using Codeception

REFACTORING USING CODECEPTION

Page 2: Refactoring using Codeception

$I->CANSEE(‘JEROEN’, ‘#VANDIJK’)

Page 3: Refactoring using Codeception

$I->USETWITTER(‘@JRVANDIJK’)

Page 4: Refactoring using Codeception

$I->AM(‘PHPBNL’, ‘.BOARD-MEMBER’)

Page 5: Refactoring using Codeception

$I->WORK(‘#ENRISE’)

Page 6: Refactoring using Codeception
Page 7: Refactoring using Codeception

NETHERLANDS

UNITED KINGDOM

BELGIUM

GERMANY

AMSTERDAM

Page 8: Refactoring using Codeception

NETHERLANDS

UNITED KINGDOM

BELGIUM

GERMANY

AMSTERDAM

NOT AMSTERDAM

Page 9: Refactoring using Codeception

NETHERLANDS

UNITED KINGDOM

BELGIUM

GERMANY

AMERSFOORT

Page 10: Refactoring using Codeception

GRAIN WAREHOUSE

Page 11: Refactoring using Codeception

REFACTORED

Page 12: Refactoring using Codeception

THIS TALK IS NOT…

Page 13: Refactoring using Codeception

THIS TALK IS NOT…

DEPENDENCY INJECTION, DECOUPLING, ENCAPSULATION, TESTABLE CODE

REFACTORING

Page 14: Refactoring using Codeception

A SIMPLE BDD STYLE TESTING FRAMEWORK WHICH IS EASY TO READ, WRITE AND DEBUG

WHAT IS CODECEPTION?

Page 15: Refactoring using Codeception

YOU WRITE IN YOUR FAVORITE EDITOR

Page 16: Refactoring using Codeception

VENDOR/BIN/CODECEPT BOOTSTRAP

COMPOSER INSTALL CODECEPTION/CODECEPTION

Page 17: Refactoring using Codeception

class_name: AcceptanceTester modules: enabled: - PhpBrowser - AcceptanceHelper config: PhpBrowser: url: 'http://www.zendcon.com/'

ACCEPTANCE.SUITE.YML

Page 18: Refactoring using Codeception

PAGE USED FOR TESTING

Page 19: Refactoring using Codeception

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

Page 20: Refactoring using Codeception

STEPS

Page 21: Refactoring using Codeception

GENERATED FILE EXTENDS ACCEPTANCETESTER CLASS

CODECEPT GENERATE:STEPOBJECT ACCEPTANCE <NAME>

Page 22: Refactoring using Codeception

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 23: Refactoring using Codeception

PAGE OBJECTS

Page 24: Refactoring using Codeception

GENERATED FILE IS JUST A CONTAINER

CODECEPT GENERATE:PAGEOBJECT ACCEPTANCE <NAME>

Page 25: Refactoring using Codeception

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

Page 26: Refactoring using Codeception

public function seeIfNameExistsViaPageObject() { HomePage::of($this)->see('zendcon'); }

USE THE OBJECT IN A TEST

Page 27: Refactoring using Codeception

VERSION COMPARISON

Page 28: Refactoring using Codeception

FROM A TECHNICAL PERSPECTIVE

MASTER !== RELEASE/NEXTGEN

Page 29: Refactoring using Codeception

FROM A FUNCTIONAL PERSPECTIVE

MASTER === RELEASE/NEXTGEN

Page 30: Refactoring using Codeception

LOST OF CODE COMING UP…

ATTENTION PLEASE

Page 31: Refactoring using Codeception

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

Page 32: Refactoring using Codeception

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

Page 33: Refactoring using Codeception

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

Page 34: Refactoring using Codeception

class_name: AcceptanceTester modules: enabled: - PhpBrowser - AcceptanceHelper config: PhpBrowser: url: 'http://www.zendcon.com/' alternate-url: 'http://zendcon.com'

ADDING ALTERNATE URL

Page 35: Refactoring using Codeception

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

Page 36: Refactoring using Codeception

public function seeIfPageHeaderIsIdentical(\CompareSteps $I) { $I->seeSameOnVersions( \HomePage::$URL, 'h2', 'h2', 'Homepage header not identical' ); }

TEST PAGE HEADER

Page 37: Refactoring using Codeception

public function seeIfFormActionIsIdentical(\CompareSteps $I) { $I->seeSameOnVersions( \HomePage::$URL, '.rsformbox1', '.rsformbox1', 'Homepage signup form not identical' ); }

TEST SIGNUP FORM

Page 38: Refactoring using Codeception

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

Page 39: Refactoring using Codeception

RUNNING THE TESTS!

Page 40: Refactoring using Codeception

EXAMPLES?

Page 41: Refactoring using Codeception

USER SPECIFIC SETTINGS

Page 42: Refactoring using Codeception

CODECEPTION.YML

VS

CODECEPTION.DIST.YML

CODECEPTION.YML.DIST

Page 43: Refactoring using Codeception

TESTING AN API

Page 44: Refactoring using Codeception

class_name: ApiTester modules: enabled: - ApiHelper - PhpBrowser - REST config: PhpBrowser: url: https://api.github.com REST: url: https://api.github.com

Page 45: Refactoring using Codeception

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(); }

Page 46: Refactoring using Codeception

ENVIRONMENTS

Page 47: Refactoring using Codeception

/** * @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') )); }

Page 48: Refactoring using Codeception

/** * @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

Page 49: Refactoring using Codeception

env: beta: config: data: accept: application/vnd.github.beta+json version3: config: data: accept: application/vnd.github.v3+json

SUITE CONFIG ADDITIONS

Page 50: Refactoring using Codeception

TESTING 2 API VERSION IN 1 RUN

CODECEPT RUN API —ENV BETA —ENV VERSION3

Page 51: Refactoring using Codeception

EXAMPLES?

Page 52: Refactoring using Codeception

READY TO DIG DEEPER?

USING MODULES

Page 53: Refactoring using Codeception

USE YOUR IMAGINATION

CODECEPT GENERATE:SUITE

Page 54: Refactoring using Codeception

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

Page 55: Refactoring using Codeception

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

Page 56: Refactoring using Codeception

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

Page 57: Refactoring using Codeception

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

Page 58: Refactoring using Codeception

FTP MODULE SIGNS IN BEFORE EVERY TEST

CAVEAT!

Page 59: Refactoring using Codeception

RUNNING THE TESTS!

Page 60: Refactoring using Codeception

GITHUB.COM/JVANDIJK/ZC14-CODECEPTION

JOIND.IN/11997


Recommended