Functional tests with TYPO3
Transcript of Functional tests with TYPO3
0Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
Functional tests with TYPO3
» Introduction
» How to start
» Running functional tests
1Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
INTRODUCTION„What is (functional) testing about?“
» test a part of your software
» not about testing your functions or classes, but processes
» from a user's point of view
» for quality assurance (QA)
„Why do I need functional tests?“
» Unit Tests don't ensure a correct workflow
» manual tests take a lot of time
» encapsulated system (database) without site-effects or dependencies
2Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„First you need a test case!“
<?php
namespace IchHabRecht\ExampleExtension\Tests\Functional;
class FirstFunctionalTest extends \TYPO3\CMS\Core\Tests\FunctionalTestCase {
}
3Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Ensure your extension is loaded!“
/**
* @var array
*/
protected $testExtensionsToLoad = array(
'typo3conf/ext/example_extension',
'typo3conf/ext/example_extension/Tests/Functional/Fixtures/Extensions/test_extension',
);
/**
* @var array
*/
protected $coreExtensionsToLoad = array(
'workspaces',
);
4Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Add additional files!“
/**
* @var array
*/
protected $pathsToLinkInTestInstance = array(
'typo3conf/ext/example_extension/Tests/Functional/Fixtures/AdditionalConfiguration.php' =>
'typo3conf/AdditionalConfiguration.php',
);
5Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Overwrite LocalConfiguration settings!“
/**
* @var array
*/
protected $configurationToUseInTestInstance = array(
'BE' => array(
'debug' => TRUE,
),
'FE' => array(
'debug' => TRUE,
),
);
6Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Initialize your infrastructure!“
protected function setUp() {
parent::setUp();
}
test folder in typo3temp is created
core is linked into test folder
test extensions are linked into typo3conf/ext
paths and files are linked
LocalConfiguration.php is written
PackageStates.php is written
bootstrap is initialized
database is created
database scheme is imported
7Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„If you need a backend user!“
protected function setUp() {
parent::setUp();
$this->setUpBackendUserFromFixture(1); // Import and log-in a default backend user
}
8Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Import your data set!“
protected function setUp() {
parent::setUp();
$this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/core/Tests/Functional/Fixtures/pages.xml');
// Import own fixtures
$fixturePath = ORIGINAL_ROOT . 'typo3conf/ext/example_extension/Tests/Functional/Fixtures';
$this->importDataSet($fixturePath . 'pages.xml'); // Import database records from the xml file
}
Fixtures, shipped by the core:
be_users.xml
pages.xml
pages_language_overlay.xml
sys_file_storage.xml
sys_language.xml
tt_content.xml
9Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Import your data set!“
typo3/sysext/core/Tests/Functional/Fixtures/pages.xml
<?xml version="1.0" encoding="utf-8"?>
<dataset>
<pages>
<uid>1</uid>
<pid>0</pid>
<title>Root</title>
<deleted>0</deleted>
<perms_everybody>15</perms_everybody>
</pages>
<pages>
<uid>2</uid>
<pid>1</pid>
<title>Dummy 1-2</title>
<deleted>0</deleted>
<perms_everybody>15</perms_everybody>
</pages>
…
</dataset>
10Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Set up the frontend!“
protected function setUp() {
parent::setUp();
$this->setUpFrontendRootPage(
1, // page id
array( // array of TypoScript files which should be included
'typo3/sysext/core/Tests/Functional/Fixtures/Frontend/JsonRenderer.ts'
)
);
}
11Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Set up the frontend!“
JsonRenderer.ts
config {
…
}
page = PAGE
page {
…
}
[globalVar = GP:L = 1]
config.sys_language_uid = 1
[end]
12Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Set up the frontend!“
JsonRenderer.ts – config.watcher
Defines tables and fields which should be collected to be returned
config.watcher {
tableFields {
pages = uid,_ORIG_uid,pid,sorting,title
sys_category = uid,_ORIG_uid,_LOCALIZED_UID,pid,sys_language_uid,title,parent,items,sys_language_uid
sys_file = uid,_ORIG_uid,_LOCALIZED_UID,pid,title,sys_language_uid
sys_file_reference = uid,_ORIG_uid,_LOCALIZED_UID,title,description,alternative,link,downloadname,
missing,identifier,file,pid,sys_language_uid,title,parent,items,sys_language_uid,uid_local,
uid_foreign,tablenames,fieldname,table_local
tt_content = uid,_ORIG_uid,_LOCALIZED_UID,pid,sorting,sys_language_uid,header,categories
}
}
13Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Set up the frontend!“
JsonRenderer.ts – page
page = PAGE
page {
10 = COA
10 {
Store current page in register
1 = LOAD_REGISTER
1.watcher.dataWrap = pages:{field:uid} // pages:1
Add current page data to records and structure array
2 = USER
2.userFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Collector->addRecordData
14Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Set up the frontend!“
JsonRenderer.ts – lib.watcherDataObject
lib.watcherDataObject = COA
lib.watcherDataObject {
1 = LOAD_REGISTER
1.watcher.dataWrap = |
2 = USER
2.userFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Collector->addRecordData
99 = RESTORE_REGISTER
}
15Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Set up the frontend!“
JsonRenderer.ts – page.10
Get page sub tree
10 = CONTENT
10 {
stdWrap.required = 1
table = pages
select {
orderBy = sorting
pidInList = this
# prevent sys_language_uid lookup
languageField = 0
}
renderObj < lib.watcherDataObject
renderObj.1.watcher.dataWrap = {register:watcher}|.__pages/pages:{field:uid} // pages:1.__pages/pages:2
}
16Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Set up the frontend!“
JsonRenderer.ts – page.10
Get content records
20 = CONTENT
20 {
table = tt_content
select {
orderBy = sorting
where = colPos=0
}
renderObj < lib.watcherDataObject
renderObj.1.watcher.dataWrap = {register:watcher}|.__contents/tt_content:{field:uid} // pages:1.__contents/tt_content:1
17Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Set up the frontend!“
JsonRenderer.ts – page.10.20
get additional information (sys_category, sys_file_reference)renderObj.10 = CONTENT
if.isTrue.field = categories
table = sys_category
select {
pidInList = root,-1
selectFields = sys_category.*
join = sys_category_record_mm ON sys_category_record_mm.uid_local = sys_category.uid
where.data = field:_ORIG_uid // field:uid
where.intval = 1
where.wrap = sys_category_record_mm.uid_foreign=|
orderBy = sys_category_record_mm.sorting_foreign
languageField = sys_category.sys_language_uid
}
renderObj < lib.watcherDataObject
renderObj.1.watcher.dataWrap = {register:watcher}|.categories/sys_category:{field:uid}
// pages:1.__contents/tt_content:1.categories/sys_category:1
18Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Set up the frontend!“
JsonRenderer.ts – page.10
store collected data for output in a section “Default”
stdWrap.postUserFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Collector->attachSection
stdWrap.postUserFunc.as = Default
19Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Set up the frontend!“
JsonRenderer.ts – page
return collected sections as json
stdWrap.postUserFunc = TYPO3\CMS\Core\Tests\Functional\Framework\Frontend\Renderer->renderSections
20Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
HOW TO START„Write your test!“
/**
* @test
*/
public function contentIsShown() {
$expectedRecords = array(
…,
);
$response = $this->getFrontendResponse(
1, // page id
0, // language id
0, // backend user id
0, // workspace id
TRUE, // fail on failure
0 // frontend user id
);
$responseContent = json_decode($response->getContent() , TRUE);
$this->assertEquals($expectedRecords, $responseContent['Default']['records']);
$this->assertInRecords($expectedRecords[0], $responseContent['Default']['records']);
}
21Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
RUNNING FUNCTIONAL TESTS„What you need!“
global PHP >= 5.5.0
composer installation of PHPUnit
{
"require-dev": {
"phpunit/phpunit": “~4.7.0",
"mikey179/vfsStream": “1.4.*@dev“
}
}
TYPO3 core source
22Nicole Cordes, T3DD15, CPS-IT Mehr Wert im Netz
RUNNING FUNCTIONAL TESTS„FINALLY RUN!“
go to your TYPO3 root directory
bin/phpunit -c typo3/sysext/core/Build/FunctionalTests.xml typo3conf/ext/example_extension/Tests/Functional
use TYPO3 source (or change the used database)
typo3DatabaseName="yourDatabase" typo3DatabaseUsername="yourUser" \
typo3DatabasePassword="yourPassword" typo3DatabaseHost="localhost" \
TYPO3_PATH_WEB=“/path/to/typo3_root” \
bin/phpunit -c /path/to/typo3_root/typo3/sysext/core/Build/FunctionalTests.xml \
/path/to/typo3_root/typo3conf/ext/example_extension/Tests/Functional