refactoring using codeception
DESCRIPTION
You must’ve heard of Unit testing… If not, then this talk is definitely for you! If you do know Unit testing, you probably ran at some point into a hurdle: “Where do I start?” And despite your best efforts, you end up not having enough tests for your application – Then that change request comes in, requiring you to change that very same complex piece of code for which you are lacking tests! How do you going refactor while maintaining all those ‘undocumented’ business rules? This talk will show how Codeception can be leveraged to refactor the visuals aspects of an application, maintaining backwards compatibility on API changes and even assist in moving to a whole different server infrastructure.TRANSCRIPT
![Page 1: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/1.jpg)
REFACTORING USING CODECEPTION
![Page 2: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/2.jpg)
$I->CANSEE(‘JEROEN’, ‘#VANDIJK’)
![Page 3: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/3.jpg)
$I->USETWITTER(‘@JRVANDIJK’)
![Page 4: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/4.jpg)
$I->AM(‘PHPBNL’, ‘.BOARD-MEMBER’)
![Page 5: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/5.jpg)
$I->WORK(‘#ENRISE’)
![Page 6: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/6.jpg)
![Page 7: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/7.jpg)
NETHERLANDS
UNITED KINGDOM
BELGIUM
GERMANY
AMSTERDAM
![Page 8: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/8.jpg)
NETHERLANDS
UNITED KINGDOM
BELGIUM
GERMANY
AMSTERDAM
NOT AMSTERDAM
![Page 9: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/9.jpg)
NETHERLANDS
UNITED KINGDOM
BELGIUM
GERMANY
AMERSFOORT
![Page 10: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/10.jpg)
GRAIN WAREHOUSE
![Page 11: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/11.jpg)
REFACTORED
![Page 12: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/12.jpg)
THIS TALK IS NOT…
![Page 13: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/13.jpg)
THIS TALK IS NOT…
DEPENDENCY INJECTION, DECOUPLING, ENCAPSULATION, TESTABLE CODE
REFACTORING
![Page 14: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/14.jpg)
A SIMPLE BDD STYLE TESTING FRAMEWORK WHICH IS EASY TO READ, WRITE AND DEBUG
WHAT IS CODECEPTION?
![Page 15: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/15.jpg)
YOU WRITE IN YOUR FAVORITE EDITOR
![Page 16: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/16.jpg)
VENDOR/BIN/CODECEPT BOOTSTRAP
COMPOSER INSTALL CODECEPTION/CODECEPTION
![Page 17: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/17.jpg)
class_name: AcceptanceTester modules: enabled: - PhpBrowser - AcceptanceHelper config: PhpBrowser: url: 'http://www.zendcon.com/'
ACCEPTANCE.SUITE.YML
![Page 18: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/18.jpg)
PAGE USED FOR TESTING
![Page 19: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/19.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/20.jpg)
STEPS
![Page 21: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/21.jpg)
GENERATED FILE EXTENDS ACCEPTANCETESTER CLASS
CODECEPT GENERATE:STEPOBJECT ACCEPTANCE <NAME>
![Page 22: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/22.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/23.jpg)
PAGE OBJECTS
![Page 24: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/24.jpg)
GENERATED FILE IS JUST A CONTAINER
CODECEPT GENERATE:PAGEOBJECT ACCEPTANCE <NAME>
![Page 25: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/25.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/26.jpg)
public function seeIfNameExistsViaPageObject() { HomePage::of($this)->see('zendcon'); }
USE THE OBJECT IN A TEST
![Page 27: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/27.jpg)
VERSION COMPARISON
![Page 28: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/28.jpg)
FROM A TECHNICAL PERSPECTIVE
MASTER !== RELEASE/NEXTGEN
![Page 29: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/29.jpg)
FROM A FUNCTIONAL PERSPECTIVE
MASTER === RELEASE/NEXTGEN
![Page 30: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/30.jpg)
LOST OF CODE COMING UP…
ATTENTION PLEASE
![Page 31: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/31.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/32.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/33.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/34.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/35.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/36.jpg)
public function seeIfPageHeaderIsIdentical(\CompareSteps $I) { $I->seeSameOnVersions( \HomePage::$URL, 'h2', 'h2', 'Homepage header not identical' ); }
TEST PAGE HEADER
![Page 37: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/37.jpg)
public function seeIfFormActionIsIdentical(\CompareSteps $I) { $I->seeSameOnVersions( \HomePage::$URL, '.rsformbox1', '.rsformbox1', 'Homepage signup form not identical' ); }
TEST SIGNUP FORM
![Page 38: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/38.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/39.jpg)
RUNNING THE TESTS!
![Page 40: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/40.jpg)
EXAMPLES?
![Page 41: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/41.jpg)
USER SPECIFIC SETTINGS
![Page 42: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/42.jpg)
CODECEPTION.YML
VS
CODECEPTION.DIST.YML
CODECEPTION.YML.DIST
![Page 43: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/43.jpg)
TESTING AN API
![Page 44: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/44.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/45.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/46.jpg)
ENVIRONMENTS
![Page 47: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/47.jpg)
/** * @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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/48.jpg)
/** * @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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/49.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/50.jpg)
TESTING 2 API VERSION IN 1 RUN
CODECEPT RUN API —ENV BETA —ENV VERSION3
![Page 51: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/51.jpg)
EXAMPLES?
![Page 52: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/52.jpg)
READY TO DIG DEEPER?
USING MODULES
![Page 53: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/53.jpg)
USE YOUR IMAGINATION
CODECEPT GENERATE:SUITE
![Page 54: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/54.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/55.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/56.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/57.jpg)
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](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/58.jpg)
FTP MODULE SIGNS IN BEFORE EVERY TEST
CAVEAT!
![Page 59: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/59.jpg)
RUNNING THE TESTS!
![Page 60: Refactoring using Codeception](https://reader033.vdocuments.mx/reader033/viewer/2022051515/558a0f29d8b42a69778b46aa/html5/thumbnails/60.jpg)
GITHUB.COM/JVANDIJK/ZC14-CODECEPTION
JOIND.IN/11997