SlideShare a Scribd company logo
TESTING
TYPO3
APPLICATIONS
CODECEPTION PHPUNIT
TRAVIS-CI
2 1 • 1 1 • 1 7
Software
Testing
PHPUnit, PHPCS, Codeception, PHPMD,
PHPStan, PHPLint, PHPCPD, Selenium, ...
2 1 • 1 1 • 1 7
A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
D Y N A M I C T E S T I N G
Execution of Code
U N I T T E S T S
F U N C T I O N A L T E S T S
S T A T I C T E S T I N G
Static Code Analysis, Review, No Code Execution
A C C E P T A N C E T E S T S
Functions, Classes, Isolated, No DB!
Complete System, DB, Environment, No real FE
Browser (UI), API, Technology Independent
1 0 0 0 F U N C T I O N A L T E S T S
A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
TESTING
TYPO3’S
CORE
9 1 0 0 U N I T T E S T S
C H R I S T I A N K U H N |   L O L L I 4 2
H T T P S : / / T Y P O 3 . C O M / B L O G / T E S T I N G - T Y P O 3 S - C O R E - P A R T - I -
I N F R A S T R U C T U R E /
2 0 0 A C C E P T A N C E T E S T S
CODECEPTION
E L E G A N T A N D E F F I C I E N T
T E S T I N G F O R P H P
<?php
class FirstCest
{
public function frontpageWorks(AcceptanceTester $I)
{
$I->amOnPage('/');
$I->see('Home');
}
}
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
composer require "codeception/codeception" --dev
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
I N S T A L L A T I O N V I A C O M P O S E R
I N S T A L L P H A R G L O B A L L Y
sudo curl -LsS http://codeception.com/codecept.phar -o
/usr/local/bin/codecept
sudo chmod a+x /usr/local/bin/codecept
codecept bootstrap
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
S E T U P
/tests
/acceptance
/functional
/unit
acceptance.suite.yml
functional.suite.yml
unit.suite.yml
codeception.yml
codecept bootstrap
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
S E T U P
T Y P O 3 E X A M P L E 1
EXT:Example
..
/Tests
/Acceptance
/tests
/acceptance
/api
acceptance.suite.yml
api.suite.yml
codeception.yml
/Functional
/Unit
..
EXT:Example
..
/tests
/acceptance
/functional
/unit
acceptance.suite.yml
functional.suite.yml
unit.suite.yml
codeception.yml
..
T Y P O 3 E X A M P L E 2
codecept init api
codecept init acceptance
codeception.yml
paths:
tests: tests
output: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs
settings:
colors: true
memory_limit: 1024M
actor_suffix: Tester
extensions:
enabled:
- CodeceptionExtensionRunFailed
A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
acceptance.suite.yml
actor: AcceptanceTester
modules:
enabled:
- PhpBrowser:
url: http://localhost:8080/
- HelperAcceptance
codeception.yml (2)
modules:
enabled:
- Db:
dsn: 'mysql:host=localhost;dbname=%CODECEPT_DB_NAME%;charset=utf8'
user: %CODECEPT_DB_USER%
password: %CODECEPT_DB_PASSWORD%
dump: tests/_data/dump.sql
cleanup: true
populate: true
populator: 'mysql -u $user -p$password $dbname < $dump'
reconnect: true
- Asserts
- PortrinoCodeceptionModuleTypo3
depends: Asserts
- REST
depends: PhpBrowser
url: http://%CODECEPT_DOMAIN%/api/
A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
G E N E R A T E T E S T S K E L E T O N S
codecept generate:cept acceptance First
<?php
$I = new AcceptanceTester($scenario);
$I->wantTo('perform actions and see result');
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
G E N E R A T E T E S T S K E L E T O N S
codecept generate:cest acceptance First
<?php
class FirstCest
{
public function _before(AcceptanceTester $I)
{
}
public function _after(AcceptanceTester $I)
{
}
public function tryToTest(AcceptanceTester $I)
{
}
}
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
W R I T E T E S T S
<?php
class FirstCest
{
public function frontpageWorks(AcceptanceTester $I)
{
$I->wantTo('Open TYPO3Camp Website');
$I->amOnUrl('https://www.typo3camp-mitteldeutschland.de/');
$I->seeInTitle('TYPO3Camp Mitteldeutschland');
$I->seeElement('.navbar');
}
}
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
R U N T E S T S
codecept run
codecept run --debug
codecept run api
codecept run acceptance FirstCest:frontpageWorks
codecept run tests/acceptance/FirstCest.php::frontpageWorks
codecept run -g fast
codecept run --env chrome
codecept run --xml
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
C O D E C E P T I O N S Y N T A X
$I->click('Login');
$I->fillField('#input-username', 'John Dough');
$I->pressKey('#input-remarks', 'foo');
A C T I O N S
$I->see('Welcome');
$I->seeInTitle('My Company');
$I->seeElement('nav');
$I->dontSeeElement('#error-message');
$this->assertEquals(123, $foo);
A S S E R T I O N S
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
A C T O R S
UnitTester, FunctionalTester, AcceptanceTester
Methods are taken from Codeception Modules
actor: AcceptanceTester
modules:
enabled:
- PhpBrowser:
url: http://localhost/myapp/
- HelperAcceptance
acceptance.suite.yml:
+ high quality
+ less bugs
+ better maintainability
+ easy refactoring
+ fun
P R O
L A U R E N H I L L S L I D E 0 1
- high experience
- high effort
- consequent
C O N T R A
A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
T E S T D R I V E N D E V E L O P M E N T ?
UNIT TESTS
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
P H P U N I T O R C O D E C E P T I O N ?
TYPO3 Unit Testing is easier with pure PHPUnit
https://github.com/TYPO3/testing-framework
https://github.com/Nimut/testing-framework
F R A M E W O R K ?
W H E R E ?
EXT:Foo/Tests/Unit/
EXT:Foo/Tests/Unit/ViewHelpers/RenderViewhelperTest.php
EXT:Foo/Tests/Unit/Fixtures/test_data.txt
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
class FooViewHelperTest extends NimutTestingFrameworkTestCaseUnitTestCase
{
protected function setUp()
{
}
protected function tearDown()
{
}
/**
* @test
*/
public function renderNothingWhenNothingToRender()
{
$this->assertEquals(1,1);
}
}
PROPHECY
{
"require-dev": {
"phpspec/prophecy": "~1.0"
}
}
A N D R É W U T T I G
T Y P O 3 U E R G R O U P
D R E S D E N
https://github.com/phpspec/prophecy
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
class FooViewHelperTest extends NimutTestingFrameworkTestCaseUnitTestCase
{
protected function setUp()
{
$environementServiceMock = $this->getMockBuilder(EnvironmentService::class)->setMethods(
[
'isEnvironmentInCliMode'
])->getMock();
$environementServiceMock->expects(static::any())
->method('isEnvironmentInCliMode')
->willReturn(true);
GeneralUtility::setSingletonInstance(
EnvironmentService::class, $environementServiceMock
);
}
}
PHPUnit MockObjects
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
class FooViewHelperTest extends NimutTestingFrameworkTestCaseUnitTestCase
{
protected function setUp()
{
$environmentServiceMock = $this->prophesize(EnvironmentService::class);
$environmentServiceMock->isEnvironmentInCliMode()->willReturn(false);
GeneralUtility::setSingletonInstance(
EnvironmentService::class, $environmentService->reveal()
);
}
Prophecy
FUNCTIONAL TESTS
D B / A P I / P H P B R O W S E R T E S T I N G
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
modules:
enabled:
- Db:
dsn: 'mysql:host=localhost;dbname=%CODECEPT_DB_NAME%;charset=utf8'
user: %CODECEPT_DB_USER%
password: %CODECEPT_DB_PASSWORD%
dump: tests/_data/dump.sql
cleanup: true
populate: true
populator: 'mysql -u $user -p$password $dbname < $dump' #faster ;-)
reconnect: true
Database - Configuration
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
$I->seeInDatabase('fe_users', array('name' => 'Andre', 'email' => 'wuttig@mail.com'));
$I->dontSeeInDatabase('fe_users', array('name' => 'Andre', 'email' => 'wuttig@mail.com'));
$mail = $I->grabFromDatabase('fe_users', 'email', array('name' => 'Andre'));
$I->haveInDatabase('fe_users', array('name' => 'miles', 'email' => 'wuttig@mail.com'));
$I->seeNumRecords(1, 'fe_users', ['name' => 'andre']);
$I->updateInDatabase('fe_users', ['isAdmin' => true], ['email' => 'miles@davis.com']);
Database Testing - Actions / Assertions / Grabbers
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
#!/bin/bash
PASSWORD=$CODECEPT_DB_PASSWORD
HOST=$CODECEPT_DB_HOST
USER=$CODECEPT_DB_USER
DATABASE=$CODECEPT_DB_NAME
DB_FILE=dump.sql
EXCLUDED_TABLES=(
be_sessions
cf_cache_hash
sys_log
...
)
...
Database Testing - Creating Testdata
https://gist.github.com/aWuttig/58599ae722a5a993172b39046ca07d0a
dump.sh
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
modules:
enabled:
- REST:
depends: PhpBrowser
url: 'http://serviceapp/api/v1/'
REST API - Configuration
L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
$I->amHttpAuthenticated('jon_snow', 'targaryen');
$I->haveHttpHeader('X-Requested-With', 'Codeception');
$I->sendGET('user');
$I->sendPOST('/user', 'name' => 'andre'));
$I->sendPUT('/user', array('id' => 123, 'name' => 'andré'));
$I->sendDELETE('/user/123');
REST API - Actions / Assertions / Grabbers
$I->seeResponseCodeIs(200);
$I->seeResponseContains('foo');
$I->seeHttpHeaderOnce('Cache-Control');
$I->seeResponseContainsJson(array('name' => 'john'));
$I->seeResponseJsonMatchesJsonPath('$.data.0.name');
$I->seeResponseMatchesJsonType(['user_id' => 'integer','is_active' => 'boolean']);
Phiremock
https://github.com/mcustiel/phiremock
M O C K H T T P R E Q U E S T
A N D R E S T A P I ´ S
A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
Phiremock
extensions:
enabled:
- CodeceptionExtensionPhiremock
config:
CodeceptionExtensionPhiremock:
listen: 127.0.0.1:18080
modules:
enabled:
- Phiremock:
host: 127.0.0.1
port: 18080
resetBeforeEachTest: false
codeception.yml
Phiremock
$I->expectARequestToRemoteServiceWithAResponse(
Phiremock::on(
A::postRequest()
->andUrl(Is::containing('type=1471426941'))
->andBody(Is::sameStringAs($data))
->andHeader(
'Authorization',
Is::equalTo(self::$token)
)
)->then(
Respond::withStatusCode(201)->andBody('')
)
);
ACCEPTANCE TESTING
W E B D R I V E R , R E A L B R O W S E R
Selenium Driver + Chrome
nohup bash -c "java -jar selenium-server-standalone.jar &" && sleep 1; cat nohup.out
- ls -al
export DISPLAY=:99.0
sh -e /etc/init.d/xvfb start
sleep 3 # give xvfb some time to start
- ls -al
X Window Virtual Framebuffer
wget -c -nc --retry-connrefused --tries=0 https://goo.gl/s4o9Vx -O 
selenium-server-standalone.jar
Selenium Server Standalone
wget -c -nc --retry-connrefused --tries=0
http://chromedriver.storage.googleapis.com/2.31/chromedriver_linux64.zip
unzip -o -q chromedriver_linux64.zip
Chrome Driver
Start Selenium Server
Webdriver - Configuration
modules:
enabled:
- WebDriver:
url: http://%CODECEPT_DOMAIN%
host: localhost
browser: chrome
restart: true
capabilities:
chromeOptions:
args: ["--headless", "--disable-gpu"]
binary: "/usr/bin/google-chrome"
codeception.yml
Webdriver - Action / Assertions
$I->click('Submit');
$I->closeTab();
$I->seeElement('.error');
$I->waitForElement('#agree_button', 30); // secs
$I->waitForText('foo', 30);
$I->switchToIFrame("another_frame");
$I->setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3');
$I->selectOption('form select[name=account]', 'Premium');
$I->resizeWindow(800, 600);
$I->scrollTo(['css' => '.checkout'], 20, 50);
$I->pressKey('#page','a');
$I->makeScreenshot('edit_page');
$myVar = $I->executeJS('return $("#myField").val()');
Page
Object
Pattern
http://codeception.com/docs/06-
ReusingTestCode#PageObjects
Reuse your testcode
Page Object Pattern
namespace Page;
class LoginPage
{
public static $URL = '/login';
public static $usernameField = '#mainForm #username';
public static $passwordField = '#mainForm input[name=password]';
public static $loginButton = '#mainForm input[type=submit]';
public function login($username, $password) {
$this->tester->fillField(self::$usernameField, $username);
$this->tester->fillField(self::$passwordField, $password);
$this->tester->click(self::$loginButton);
return $this;
}
}
Page Object Pattern
class LoginCest
{
public function loginAsUser(AcceptanceTester $I, LoginPage $loginPage) {
$loginPage->open()->login('wuttig','123456');
$I->seeElement('#userprofile');
}
}
Webdriver - Action / Assertions
namespace Page;
class Login
{
public static $URL = '/login';
public static $usernameField = '#mainForm #username';
public static $passwordField = '#mainForm input[name=password]';
public static $loginButton = '#mainForm input[type=submit]';
public function login($username, $password) {
$this->tester->fillField(self::$usernameField, $username);
$this->tester->fillField(self::$passwordField, $password);
$this->tester->click(self::$loginButton);
return $this;
}
}
Multi
Session
Testing
http://codeception.com/docs/03-
AcceptanceTests#multi-session-testing
T E S T I N G C O N C U R R E N T
S E S S I O N S
A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
Multi Session Testing
$I->amOnPage('/messages');
$david = $I->haveFriend('david');
$david->does(function(AcceptanceTester $I) {
$I->amOnPage('/messages/new');
$I->fillField('body', 'Hello all!');
$I->click('Send');
$I->see('Hello all!', '.message');
});
$I->wait(3);
$I->see('Hello all!', '.message');
$david->leave();
Friends
Mailhog https://github.com/mailhog/MailHog
W E B A P I B A S E D S M T P
T E S T I N G
A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
https://github.com/ericmartel/codeception-email-mailhog
Mailhog - Web API based SMTP Testing
"require-dev": {
"ericmartel/codeception-email-mailhog": "^1.0"
}
modules:
enabled:
- MailHog:
url: %CODECEPT_DOMAIN%
port: '8025'
A N D R É W U T T I G
Mailhog - Web API based SMTP Testing
$I->fetchEmails();
$I->accessInboxFor('testuser@example.com');
$I->haveEmails();
$I->haveUnreadEmails();
$I->seeInOpenedEmailSubject('Your Password Reset Link');
$I->seeInOpenedEmailBody('Follow this link to reset your password');
$I->seeInOpenedEmailRecipients('testuser@example.com');
Codeception
Helper https://github.com/portrino/codeception-helper-module
H E L P E R M O D U L E S F O R
T Y P O 3 A N D S H O P W A R E
A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
Codeception TYPO3 Helper
modules:
enabled:
- PortrinoCodeceptionModuleTypo3:
depends: Asserts
domain: www.example.com
$I->executeCommand(Typo3Command::CACHE_FLUSH);
$I->executeSchedulerTask($taskId, $force = false, $environmentVariables = []);
$I->flushCache($force = false, $filesOnly = false);
$I->flushCacheGroups($groups);
$I->importIntoDatabase($file);
Actions
Interfaces / Constants
PortrinoCodeceptionInterfacesDatabaseTablesTypo3Database::FE_USERS
PortrinoCodeceptionInterfacesCookiesTypo3Cookie::FE_USER_COOKIE
PortrinoCodeceptionInterfacesCommandsTypo3Command::CACHE_FLUSH
Codeception TYPO3 Helper
CodeceptionUtilFixtures::add(
'fe_user',
[
'__model' => PortrinoCodeceptionModelTypo3Typo3FrontendUser::class,
'name' => 'andre',
'email' => 'wuttig@mail.com'
]
);
Fixture Models
_boostrap.php
$frontendUser = PortrinoCodeceptionUtilFixtures::get('fe_user');
$I->see($frontendUser->email);
FrontendUserTest.php
MORE
CODECEPTION
MODULES
ANGULARJS, SYMFONY, DOCTRINE ORM,
LARAVEL5, FILE, CLI, YII2, ZF
2 1 • 1 1 • 1 7
DOCTRINE-ORM, SYMFONY, LARAVEL, ZEND FRAMEWORK,
ANGULARJS, CLI, FILE, REDIS
MORE CODECEPTION MODULES
FROM @PORTRINO:
codeception-sitemap-module
(https://github.com/portrino/codeception-sitemap-module)
codeception-yandex-module
(https://github.com/portrino/codeception-yandex-module)
codeception-stripe-module
(https://github.com/portrino/codeception-stripe-module)
codeception-cleverreach-module
(https://github.com/portrino/codeception-cleverreach-module)
TRAVIS
CI
C O N T I N O U S I N T E G R A T I O N
https://travis-ci.org/
2 1 • 1 1 • 1 7
TRAVIS CI
language: php
matrix:
fast_finish: true
include:
- php: 5.5
env: TYPO3_VERSION=^7.6 PHPSTAN=0 COMPAT=1
- php: 5.6
env: TYPO3_VERSION=^7.6 PHPSTAN=0 COMPAT=1
- php: 7.0
env: TYPO3_VERSION=^7.6 PHPSTAN=1 COMPAT=0
- php: 7.1
env: TYPO3_VERSION=^7.6 PHPSTAN=1 COMPAT=0
- php: 7.0
env: TYPO3_VERSION=^8.7 PHPSTAN=1 COMPAT=0
- php: 7.1
env: TYPO3_VERSION=^8.7 PHPSTAN=1 COMPAT=0
sudo: false
travis.yml
TRAVIS CI
travis.yml
before_install:
- mysql -e 'CREATE DATABASE typo3 CHARACTER SET utf8 COLLATE utf8_general_ci;'
- composer self-update
install:
- composer update typo3/cms=$TYPO3_VERSION
before_script:
- export TYPO3_PATH_WEB=$PWD/.build/web
- mkdir -p .build/web/typo3conf
- .build/bin/typo3cms install:setup --non-interactive --database-host-name=127.0.0.1
--database-port=3306 --database-user-name=travis --database-name=typo3 --use-existing-
database --admin-user-name=travis --admin-password=travis123456! --site-setup-
type=site
- .build/bin/typo3cms install:generatepackagestates
- .build/bin/typo3cms database:updateschema *.add,*.change
- .build/bin/typo3cms cache:flushgroups system
- .build/bin/typo3cms configuration:set --path SYS/trustedHostsPattern --value ".*"
- if [[ $COMPAT = 0 ]]; then .build/bin/typo3cms configuration:set --path
SYS/debugExceptionHandler --value
"PortrinoTypo3WhoopsErrorWhoopsExceptionHandler"; fi
TRAVIS CI
travis.yml
script:
- >
echo;
echo "Running PHP PSR-2 coding standard checks (phpcs)";
.build/bin/phpcs --standard=PSR2 --warning-severity=0 src/;
- >
echo;
echo "Running static code analysis (phpstan)";
if [[ $PHPSTAN = 1 ]]; then composer require --dev phpstan/phpstan:^0.8
&& .build/bin/phpstan analyse -l 7 src/Error; fi
- >
echo;
echo "Running tests (codeception)";
.build/bin/codecept run --debug
2 1 • 1 1 • 1 7
@AndreWuttig
@aWuttig
@wuuTANG
THANK
YOU!
ANDRÉ WUTTIG
2 1 • 1 1 • 1 7

More Related Content

PDF
Semantic Web & TYPO3
PPTX
Representing Material Culture Online: Historic Clothing in Omeka
PDF
PHP Backdoor: The rise of the vuln
PDF
Php web backdoor obfuscation
PDF
Code obfuscation, php shells & more
PPTX
Inside a Digital Collection: Historic Clothing in Omeka
PPT
wreewrer
TXT
Semantic Web & TYPO3
Representing Material Culture Online: Historic Clothing in Omeka
PHP Backdoor: The rise of the vuln
Php web backdoor obfuscation
Code obfuscation, php shells & more
Inside a Digital Collection: Historic Clothing in Omeka
wreewrer

What's hot (20)

PDF
Using Phing for Fun and Profit
PDF
Perl6 in-production
PDF
TXT
Wsomdp
PPTX
Pulsar Architectural Patterns for CI/CD Automation and Self-Service
PDF
Geb for Testing Your Grails Application GR8Conf India 2016
PDF
PHP7 - Scalar Type Hints & Return Types
PDF
The Perl6 Type System
PPTX
API Pain Points (PHPNE)
PDF
Perl6 grammars
PPT
Api pain points
PPTX
Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)
KEY
SPL, not a bridge too far
PPTX
Creating own language made easy
KEY
Web Development with CoffeeScript and Sass
PDF
php[world] 2016 - You Don’t Need Node.js - Async Programming in PHP
PDF
Service intergration
PPT
Php Rss
Using Phing for Fun and Profit
Perl6 in-production
Wsomdp
Pulsar Architectural Patterns for CI/CD Automation and Self-Service
Geb for Testing Your Grails Application GR8Conf India 2016
PHP7 - Scalar Type Hints & Return Types
The Perl6 Type System
API Pain Points (PHPNE)
Perl6 grammars
Api pain points
Introduction to CodeIgniter (RefreshAugusta, 20 May 2009)
SPL, not a bridge too far
Creating own language made easy
Web Development with CoffeeScript and Sass
php[world] 2016 - You Don’t Need Node.js - Async Programming in PHP
Service intergration
Php Rss
Ad

Similar to Testing TYPO3 Applications (20)

PDF
Acceptance testing in php with Codeception - Techmeetup Edinburgh
PPTX
Codeception
PDF
Testing with Codeception (Webelement #30)
PDF
Leveling Up With Unit Testing - LonghornPHP 2022
PDF
Refactoring using Codeception
KEY
Workshop unittesting
PDF
Testing mit Codeception: Full-stack testing PHP framework
PDF
Codeception presentation
PPTX
Automation testing with Drupal 8
PDF
Mykhailo Bodnarchuk "The history of the Codeception project"
PDF
Testing PHP with Codeception
PDF
Leveling Up With Unit Testing - php[tek] 2023
PPTX
Test in action – week 1
PPT
Unit testing
ZIP
Test
PDF
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
KEY
PHPUnit testing to Zend_Test
PDF
Getting started with TDD - Confoo 2014
KEY
Developer testing 201: When to Mock and When to Integrate
PPTX
Code ceptioninstallation
Acceptance testing in php with Codeception - Techmeetup Edinburgh
Codeception
Testing with Codeception (Webelement #30)
Leveling Up With Unit Testing - LonghornPHP 2022
Refactoring using Codeception
Workshop unittesting
Testing mit Codeception: Full-stack testing PHP framework
Codeception presentation
Automation testing with Drupal 8
Mykhailo Bodnarchuk "The history of the Codeception project"
Testing PHP with Codeception
Leveling Up With Unit Testing - php[tek] 2023
Test in action – week 1
Unit testing
Test
Test-driven Development with Drupal and Codeception (DrupalCamp Brighton)
PHPUnit testing to Zend_Test
Getting started with TDD - Confoo 2014
Developer testing 201: When to Mock and When to Integrate
Code ceptioninstallation
Ad

Recently uploaded (20)

PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
System and Network Administraation Chapter 3
PDF
top salesforce developer skills in 2025.pdf
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
AI in Product Development-omnex systems
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PPTX
Online Work Permit System for Fast Permit Processing
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PPTX
L1 - Introduction to python Backend.pptx
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
medical staffing services at VALiNTRY
PDF
Understanding Forklifts - TECH EHS Solution
PPTX
ISO 45001 Occupational Health and Safety Management System
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Softaken Excel to vCard Converter Software.pdf
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
Odoo Companies in India – Driving Business Transformation.pdf
Adobe Illustrator 28.6 Crack My Vision of Vector Design
System and Network Administraation Chapter 3
top salesforce developer skills in 2025.pdf
Design an Analysis of Algorithms I-SECS-1021-03
AI in Product Development-omnex systems
Wondershare Filmora 15 Crack With Activation Key [2025
Online Work Permit System for Fast Permit Processing
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
L1 - Introduction to python Backend.pptx
Operating system designcfffgfgggggggvggggggggg
medical staffing services at VALiNTRY
Understanding Forklifts - TECH EHS Solution
ISO 45001 Occupational Health and Safety Management System

Testing TYPO3 Applications

  • 2. Software Testing PHPUnit, PHPCS, Codeception, PHPMD, PHPStan, PHPLint, PHPCPD, Selenium, ... 2 1 • 1 1 • 1 7 A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N D Y N A M I C T E S T I N G Execution of Code U N I T T E S T S F U N C T I O N A L T E S T S S T A T I C T E S T I N G Static Code Analysis, Review, No Code Execution A C C E P T A N C E T E S T S Functions, Classes, Isolated, No DB! Complete System, DB, Environment, No real FE Browser (UI), API, Technology Independent
  • 3. 1 0 0 0 F U N C T I O N A L T E S T S A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N TESTING TYPO3’S CORE 9 1 0 0 U N I T T E S T S C H R I S T I A N K U H N |   L O L L I 4 2 H T T P S : / / T Y P O 3 . C O M / B L O G / T E S T I N G - T Y P O 3 S - C O R E - P A R T - I - I N F R A S T R U C T U R E / 2 0 0 A C C E P T A N C E T E S T S
  • 4. CODECEPTION E L E G A N T A N D E F F I C I E N T T E S T I N G F O R P H P
  • 5. <?php class FirstCest { public function frontpageWorks(AcceptanceTester $I) { $I->amOnPage('/'); $I->see('Home'); } } L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
  • 6. composer require "codeception/codeception" --dev L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N I N S T A L L A T I O N V I A C O M P O S E R I N S T A L L P H A R G L O B A L L Y sudo curl -LsS http://codeception.com/codecept.phar -o /usr/local/bin/codecept sudo chmod a+x /usr/local/bin/codecept
  • 7. codecept bootstrap L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N S E T U P /tests /acceptance /functional /unit acceptance.suite.yml functional.suite.yml unit.suite.yml codeception.yml
  • 8. codecept bootstrap L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N S E T U P T Y P O 3 E X A M P L E 1 EXT:Example .. /Tests /Acceptance /tests /acceptance /api acceptance.suite.yml api.suite.yml codeception.yml /Functional /Unit .. EXT:Example .. /tests /acceptance /functional /unit acceptance.suite.yml functional.suite.yml unit.suite.yml codeception.yml .. T Y P O 3 E X A M P L E 2 codecept init api codecept init acceptance
  • 9. codeception.yml paths: tests: tests output: tests/_output data: tests/_data support: tests/_support envs: tests/_envs settings: colors: true memory_limit: 1024M actor_suffix: Tester extensions: enabled: - CodeceptionExtensionRunFailed A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N acceptance.suite.yml actor: AcceptanceTester modules: enabled: - PhpBrowser: url: http://localhost:8080/ - HelperAcceptance
  • 10. codeception.yml (2) modules: enabled: - Db: dsn: 'mysql:host=localhost;dbname=%CODECEPT_DB_NAME%;charset=utf8' user: %CODECEPT_DB_USER% password: %CODECEPT_DB_PASSWORD% dump: tests/_data/dump.sql cleanup: true populate: true populator: 'mysql -u $user -p$password $dbname < $dump' reconnect: true - Asserts - PortrinoCodeceptionModuleTypo3 depends: Asserts - REST depends: PhpBrowser url: http://%CODECEPT_DOMAIN%/api/ A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
  • 11. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N G E N E R A T E T E S T S K E L E T O N S codecept generate:cept acceptance First <?php $I = new AcceptanceTester($scenario); $I->wantTo('perform actions and see result');
  • 12. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N G E N E R A T E T E S T S K E L E T O N S codecept generate:cest acceptance First <?php class FirstCest { public function _before(AcceptanceTester $I) { } public function _after(AcceptanceTester $I) { } public function tryToTest(AcceptanceTester $I) { } }
  • 13. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N W R I T E T E S T S <?php class FirstCest { public function frontpageWorks(AcceptanceTester $I) { $I->wantTo('Open TYPO3Camp Website'); $I->amOnUrl('https://www.typo3camp-mitteldeutschland.de/'); $I->seeInTitle('TYPO3Camp Mitteldeutschland'); $I->seeElement('.navbar'); } }
  • 14. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N R U N T E S T S codecept run codecept run --debug codecept run api codecept run acceptance FirstCest:frontpageWorks codecept run tests/acceptance/FirstCest.php::frontpageWorks codecept run -g fast codecept run --env chrome codecept run --xml
  • 15. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N C O D E C E P T I O N S Y N T A X $I->click('Login'); $I->fillField('#input-username', 'John Dough'); $I->pressKey('#input-remarks', 'foo'); A C T I O N S $I->see('Welcome'); $I->seeInTitle('My Company'); $I->seeElement('nav'); $I->dontSeeElement('#error-message'); $this->assertEquals(123, $foo); A S S E R T I O N S
  • 16. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N A C T O R S UnitTester, FunctionalTester, AcceptanceTester Methods are taken from Codeception Modules actor: AcceptanceTester modules: enabled: - PhpBrowser: url: http://localhost/myapp/ - HelperAcceptance acceptance.suite.yml:
  • 17. + high quality + less bugs + better maintainability + easy refactoring + fun P R O L A U R E N H I L L S L I D E 0 1 - high experience - high effort - consequent C O N T R A A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N T E S T D R I V E N D E V E L O P M E N T ?
  • 19. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N P H P U N I T O R C O D E C E P T I O N ? TYPO3 Unit Testing is easier with pure PHPUnit https://github.com/TYPO3/testing-framework https://github.com/Nimut/testing-framework F R A M E W O R K ? W H E R E ? EXT:Foo/Tests/Unit/ EXT:Foo/Tests/Unit/ViewHelpers/RenderViewhelperTest.php EXT:Foo/Tests/Unit/Fixtures/test_data.txt
  • 20. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N class FooViewHelperTest extends NimutTestingFrameworkTestCaseUnitTestCase { protected function setUp() { } protected function tearDown() { } /** * @test */ public function renderNothingWhenNothingToRender() { $this->assertEquals(1,1); } }
  • 21. PROPHECY { "require-dev": { "phpspec/prophecy": "~1.0" } } A N D R É W U T T I G T Y P O 3 U E R G R O U P D R E S D E N https://github.com/phpspec/prophecy
  • 22. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N class FooViewHelperTest extends NimutTestingFrameworkTestCaseUnitTestCase { protected function setUp() { $environementServiceMock = $this->getMockBuilder(EnvironmentService::class)->setMethods( [ 'isEnvironmentInCliMode' ])->getMock(); $environementServiceMock->expects(static::any()) ->method('isEnvironmentInCliMode') ->willReturn(true); GeneralUtility::setSingletonInstance( EnvironmentService::class, $environementServiceMock ); } } PHPUnit MockObjects
  • 23. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N class FooViewHelperTest extends NimutTestingFrameworkTestCaseUnitTestCase { protected function setUp() { $environmentServiceMock = $this->prophesize(EnvironmentService::class); $environmentServiceMock->isEnvironmentInCliMode()->willReturn(false); GeneralUtility::setSingletonInstance( EnvironmentService::class, $environmentService->reveal() ); } Prophecy
  • 24. FUNCTIONAL TESTS D B / A P I / P H P B R O W S E R T E S T I N G
  • 25. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N modules: enabled: - Db: dsn: 'mysql:host=localhost;dbname=%CODECEPT_DB_NAME%;charset=utf8' user: %CODECEPT_DB_USER% password: %CODECEPT_DB_PASSWORD% dump: tests/_data/dump.sql cleanup: true populate: true populator: 'mysql -u $user -p$password $dbname < $dump' #faster ;-) reconnect: true Database - Configuration
  • 26. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N $I->seeInDatabase('fe_users', array('name' => 'Andre', 'email' => 'wuttig@mail.com')); $I->dontSeeInDatabase('fe_users', array('name' => 'Andre', 'email' => 'wuttig@mail.com')); $mail = $I->grabFromDatabase('fe_users', 'email', array('name' => 'Andre')); $I->haveInDatabase('fe_users', array('name' => 'miles', 'email' => 'wuttig@mail.com')); $I->seeNumRecords(1, 'fe_users', ['name' => 'andre']); $I->updateInDatabase('fe_users', ['isAdmin' => true], ['email' => 'miles@davis.com']); Database Testing - Actions / Assertions / Grabbers
  • 27. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N #!/bin/bash PASSWORD=$CODECEPT_DB_PASSWORD HOST=$CODECEPT_DB_HOST USER=$CODECEPT_DB_USER DATABASE=$CODECEPT_DB_NAME DB_FILE=dump.sql EXCLUDED_TABLES=( be_sessions cf_cache_hash sys_log ... ) ... Database Testing - Creating Testdata https://gist.github.com/aWuttig/58599ae722a5a993172b39046ca07d0a dump.sh
  • 28. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N modules: enabled: - REST: depends: PhpBrowser url: 'http://serviceapp/api/v1/' REST API - Configuration
  • 29. L A U R E N H I L L S L I D E 0 6A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N $I->amHttpAuthenticated('jon_snow', 'targaryen'); $I->haveHttpHeader('X-Requested-With', 'Codeception'); $I->sendGET('user'); $I->sendPOST('/user', 'name' => 'andre')); $I->sendPUT('/user', array('id' => 123, 'name' => 'andré')); $I->sendDELETE('/user/123'); REST API - Actions / Assertions / Grabbers $I->seeResponseCodeIs(200); $I->seeResponseContains('foo'); $I->seeHttpHeaderOnce('Cache-Control'); $I->seeResponseContainsJson(array('name' => 'john')); $I->seeResponseJsonMatchesJsonPath('$.data.0.name'); $I->seeResponseMatchesJsonType(['user_id' => 'integer','is_active' => 'boolean']);
  • 30. Phiremock https://github.com/mcustiel/phiremock M O C K H T T P R E Q U E S T A N D R E S T A P I ´ S A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
  • 33. ACCEPTANCE TESTING W E B D R I V E R , R E A L B R O W S E R
  • 34. Selenium Driver + Chrome nohup bash -c "java -jar selenium-server-standalone.jar &" && sleep 1; cat nohup.out - ls -al export DISPLAY=:99.0 sh -e /etc/init.d/xvfb start sleep 3 # give xvfb some time to start - ls -al X Window Virtual Framebuffer wget -c -nc --retry-connrefused --tries=0 https://goo.gl/s4o9Vx -O selenium-server-standalone.jar Selenium Server Standalone wget -c -nc --retry-connrefused --tries=0 http://chromedriver.storage.googleapis.com/2.31/chromedriver_linux64.zip unzip -o -q chromedriver_linux64.zip Chrome Driver Start Selenium Server
  • 35. Webdriver - Configuration modules: enabled: - WebDriver: url: http://%CODECEPT_DOMAIN% host: localhost browser: chrome restart: true capabilities: chromeOptions: args: ["--headless", "--disable-gpu"] binary: "/usr/bin/google-chrome" codeception.yml
  • 36. Webdriver - Action / Assertions $I->click('Submit'); $I->closeTab(); $I->seeElement('.error'); $I->waitForElement('#agree_button', 30); // secs $I->waitForText('foo', 30); $I->switchToIFrame("another_frame"); $I->setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); $I->selectOption('form select[name=account]', 'Premium'); $I->resizeWindow(800, 600); $I->scrollTo(['css' => '.checkout'], 20, 50); $I->pressKey('#page','a'); $I->makeScreenshot('edit_page'); $myVar = $I->executeJS('return $("#myField").val()');
  • 38. Page Object Pattern namespace Page; class LoginPage { public static $URL = '/login'; public static $usernameField = '#mainForm #username'; public static $passwordField = '#mainForm input[name=password]'; public static $loginButton = '#mainForm input[type=submit]'; public function login($username, $password) { $this->tester->fillField(self::$usernameField, $username); $this->tester->fillField(self::$passwordField, $password); $this->tester->click(self::$loginButton); return $this; } }
  • 39. Page Object Pattern class LoginCest { public function loginAsUser(AcceptanceTester $I, LoginPage $loginPage) { $loginPage->open()->login('wuttig','123456'); $I->seeElement('#userprofile'); } }
  • 40. Webdriver - Action / Assertions namespace Page; class Login { public static $URL = '/login'; public static $usernameField = '#mainForm #username'; public static $passwordField = '#mainForm input[name=password]'; public static $loginButton = '#mainForm input[type=submit]'; public function login($username, $password) { $this->tester->fillField(self::$usernameField, $username); $this->tester->fillField(self::$passwordField, $password); $this->tester->click(self::$loginButton); return $this; } }
  • 41. Multi Session Testing http://codeception.com/docs/03- AcceptanceTests#multi-session-testing T E S T I N G C O N C U R R E N T S E S S I O N S A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
  • 42. Multi Session Testing $I->amOnPage('/messages'); $david = $I->haveFriend('david'); $david->does(function(AcceptanceTester $I) { $I->amOnPage('/messages/new'); $I->fillField('body', 'Hello all!'); $I->click('Send'); $I->see('Hello all!', '.message'); }); $I->wait(3); $I->see('Hello all!', '.message'); $david->leave(); Friends
  • 43. Mailhog https://github.com/mailhog/MailHog W E B A P I B A S E D S M T P T E S T I N G A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N https://github.com/ericmartel/codeception-email-mailhog
  • 44. Mailhog - Web API based SMTP Testing "require-dev": { "ericmartel/codeception-email-mailhog": "^1.0" } modules: enabled: - MailHog: url: %CODECEPT_DOMAIN% port: '8025' A N D R É W U T T I G
  • 45. Mailhog - Web API based SMTP Testing $I->fetchEmails(); $I->accessInboxFor('testuser@example.com'); $I->haveEmails(); $I->haveUnreadEmails(); $I->seeInOpenedEmailSubject('Your Password Reset Link'); $I->seeInOpenedEmailBody('Follow this link to reset your password'); $I->seeInOpenedEmailRecipients('testuser@example.com');
  • 46. Codeception Helper https://github.com/portrino/codeception-helper-module H E L P E R M O D U L E S F O R T Y P O 3 A N D S H O P W A R E A N D R É W U T T I G T Y P O 3 U S E R G R O U P D R E S D E N
  • 47. Codeception TYPO3 Helper modules: enabled: - PortrinoCodeceptionModuleTypo3: depends: Asserts domain: www.example.com $I->executeCommand(Typo3Command::CACHE_FLUSH); $I->executeSchedulerTask($taskId, $force = false, $environmentVariables = []); $I->flushCache($force = false, $filesOnly = false); $I->flushCacheGroups($groups); $I->importIntoDatabase($file); Actions Interfaces / Constants PortrinoCodeceptionInterfacesDatabaseTablesTypo3Database::FE_USERS PortrinoCodeceptionInterfacesCookiesTypo3Cookie::FE_USER_COOKIE PortrinoCodeceptionInterfacesCommandsTypo3Command::CACHE_FLUSH
  • 48. Codeception TYPO3 Helper CodeceptionUtilFixtures::add( 'fe_user', [ '__model' => PortrinoCodeceptionModelTypo3Typo3FrontendUser::class, 'name' => 'andre', 'email' => 'wuttig@mail.com' ] ); Fixture Models _boostrap.php $frontendUser = PortrinoCodeceptionUtilFixtures::get('fe_user'); $I->see($frontendUser->email); FrontendUserTest.php
  • 49. MORE CODECEPTION MODULES ANGULARJS, SYMFONY, DOCTRINE ORM, LARAVEL5, FILE, CLI, YII2, ZF 2 1 • 1 1 • 1 7
  • 50. DOCTRINE-ORM, SYMFONY, LARAVEL, ZEND FRAMEWORK, ANGULARJS, CLI, FILE, REDIS MORE CODECEPTION MODULES FROM @PORTRINO: codeception-sitemap-module (https://github.com/portrino/codeception-sitemap-module) codeception-yandex-module (https://github.com/portrino/codeception-yandex-module) codeception-stripe-module (https://github.com/portrino/codeception-stripe-module) codeception-cleverreach-module (https://github.com/portrino/codeception-cleverreach-module)
  • 51. TRAVIS CI C O N T I N O U S I N T E G R A T I O N https://travis-ci.org/ 2 1 • 1 1 • 1 7
  • 52. TRAVIS CI language: php matrix: fast_finish: true include: - php: 5.5 env: TYPO3_VERSION=^7.6 PHPSTAN=0 COMPAT=1 - php: 5.6 env: TYPO3_VERSION=^7.6 PHPSTAN=0 COMPAT=1 - php: 7.0 env: TYPO3_VERSION=^7.6 PHPSTAN=1 COMPAT=0 - php: 7.1 env: TYPO3_VERSION=^7.6 PHPSTAN=1 COMPAT=0 - php: 7.0 env: TYPO3_VERSION=^8.7 PHPSTAN=1 COMPAT=0 - php: 7.1 env: TYPO3_VERSION=^8.7 PHPSTAN=1 COMPAT=0 sudo: false travis.yml
  • 53. TRAVIS CI travis.yml before_install: - mysql -e 'CREATE DATABASE typo3 CHARACTER SET utf8 COLLATE utf8_general_ci;' - composer self-update install: - composer update typo3/cms=$TYPO3_VERSION before_script: - export TYPO3_PATH_WEB=$PWD/.build/web - mkdir -p .build/web/typo3conf - .build/bin/typo3cms install:setup --non-interactive --database-host-name=127.0.0.1 --database-port=3306 --database-user-name=travis --database-name=typo3 --use-existing- database --admin-user-name=travis --admin-password=travis123456! --site-setup- type=site - .build/bin/typo3cms install:generatepackagestates - .build/bin/typo3cms database:updateschema *.add,*.change - .build/bin/typo3cms cache:flushgroups system - .build/bin/typo3cms configuration:set --path SYS/trustedHostsPattern --value ".*" - if [[ $COMPAT = 0 ]]; then .build/bin/typo3cms configuration:set --path SYS/debugExceptionHandler --value "PortrinoTypo3WhoopsErrorWhoopsExceptionHandler"; fi
  • 54. TRAVIS CI travis.yml script: - > echo; echo "Running PHP PSR-2 coding standard checks (phpcs)"; .build/bin/phpcs --standard=PSR2 --warning-severity=0 src/; - > echo; echo "Running static code analysis (phpstan)"; if [[ $PHPSTAN = 1 ]]; then composer require --dev phpstan/phpstan:^0.8 && .build/bin/phpstan analyse -l 7 src/Error; fi - > echo; echo "Running tests (codeception)"; .build/bin/codecept run --debug
  • 55. 2 1 • 1 1 • 1 7 @AndreWuttig @aWuttig @wuuTANG
  • 56. THANK YOU! ANDRÉ WUTTIG 2 1 • 1 1 • 1 7