I am using Codeception to make acceptance tests for Symfony project. I need to test everything, this means testing pages (html content) as well as the ajax calls they perform (JSON content).
I have enabled the Symfony2 module in my suite settings but I find few methods in it to check JSON strings, so I guess I'm supposed to enable the REST module as well. However, if I do so, other previously existing tests fail.
For instance, this simple test:
public function privateExtranetHome(AcceptanceTester $I)
{
$I->wantTo('test something');
$I->amOnRoute('acme_site_home.es');
$I->assertEquals(
'container',
$I->grabAttributeFrom('#container-slider', 'class')
);
}
This is not a JSON testing test, just an already existing test in my Cest class, that passed when I only had the Symfony2 module enabled, and fails now that I added the REST module. The error message is :
Scenario:
* I am on route "acme_site_home.es"
[Page] http://localhost/es
[User] anon. []
* I grab attribute from "#container-slider","class"
Fatal error: Call to a member function hasAttribute() on null in [...]\Codeception\Module\REST.php on line 993
Maybe the amOnRoute() method is incompatible with the REST module, because when the latter is enabled, I get an empty response. But therefore my question is: is there some documentation, somewhere which states which modules are incompatible and should not be enabled together? Or should I take as a rule of thumb to use a separate suite for each module?
Just in case, my acceptance suite settings are as follows:
class_name: AcceptanceTester
modules:
enabled:
- Asserts
- Db
- Symfony2
- Doctrine2
- \Tests\Helper\Acceptance
And my Codeception settings:
namespace: Tests
actor: Tester
paths:
tests: tests
log: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs
settings:
bootstrap: _bootstrap.php
colors: true
memory_limit: 1024M
extensions:
enabled: [ Codeception\Extension\RunFailed ]
modules:
config:
Db:
dsn: 'mysql:host=localhost;dbname=acme_test'
user: 'root'
password: 'blahblah'
dump: 'tests/_data/dump.sql'
populate: false
cleanup: false
Doctrine2:
depends: Symfony2
cleanup: false
PhpBrowser:
url: http://acme.com
WebDriver:
browser: firefox
url: http://acme.com
REST:
depends: Symfony2
url: http://acme.com
REST module is compatible with and relies on framework modules to process requests.
However you discovered an unreported incompatibility - grabAttributeFrom method is defined both modules - Symfony2 and REST. I will raise an issue for that.
There is one workaround you could use - grabAttributeFrom is defined in XML part of REST module, so if your REST requests return only JSON, you could enable JSON functionality only.
REST:
depends: Symfony2
part: JSON
Related
I have set up a functional test following the tutorials at:
http://codeception.com/docs/04-FunctionalTests
http://codeception.com/docs/modules/Symfony
http://codeception.com/09-04-2015/using-codeception-for-symfony-projects.html
The main difference is that I've set up Codeception the traditional way because I don't want to mix test code with project code.
This is my functional test (I know it's not actually testing anything):
<?php
class MyFirstCest {
public function _before(FunctionalTester $I) {
}
public function _after(FunctionalTester $I) {
}
// tests
public function tryToTest(FunctionalTester $I) {
$I->amOnPage('/app/login/');
}
}
When I run the functional test I get:
[RuntimeException] Call to undefined method FunctionalTester::amOnPage
When I rebuild Codeception, I get:
Building Actor classes for suites: acceptance, functional, unit
-> AcceptanceTesterActions.php generated successfully. 0 methods added
\AcceptanceTester includes modules: PhpBrowser, \Helper\Acceptance
-> FunctionalTesterActions.php generated successfully. 0 methods added
\FunctionalTester includes modules:
-> UnitTesterActions.php generated successfully. 0 methods added
\UnitTester includes modules: Asserts, \Helper\Unit
The critical part seems to be \FunctionalTester includes modules: which is empty.
My functional.suite.yml file looks like this:
actor: FunctionalTester
modules:
- Symfony:
app_path: 'app'
environment: 'local_test'
class_name: FunctionalTester
modules:
enabled:
- Symfony2:
app_path: 'path/to/app'
var_path: 'path/to/app'
- Doctrine2:
depends: Symfony2
- \Helper\Functional
- PhpBrowser:
url: dev.hmr-app
- \AcmeBundle\Helper\Functional
where the Symfony app lives in path/to/app. I know there's a lot of junk in there, but that's because I've been experimenting, trying to get it to work.
What am I doing wrong?
I think that your problem is that you have
modules:
- Symfony:
app_path: 'app'
environment: 'local_test'
in the config.
That section is completely misplaced and it probably is causing you issues.
Please remove it and rename Symfony2 with Symfony in enabled section.
Also make sure that you are using the latest version of Codeception.
I am writing acceptance codeception tests on a web application. It will require me to check headers, specifically response codes. I have found that the codeception REST module can be used, but it appears to require phpbrowser. I am required though to use browserstack. How would the configuration look using browserstack as aposed to phpbrowser.
My acceptance.suite.yml is currently set up like:
chrome-dev:
modules:
enabled:
- WebDriver
- \Helper\
config:
WebDriver:
url: 'https://XXXXXXXXXXXXXXXXXX.com'
host: 'XXXXXXXX#XXXXXXXX.com:XXXXXXXXXX.browserstack.com'
port: 80
browser: 'chrome'
window_size: maximize
capabilities:
'os': 'Windows'
'os_version': '10'
'browser_version': '57'
'acceptSslCerts': true
'resolution': '1600x1200'
'browserstack.chrome.enablePopups': true
'browserstack.chrome.allowAllCookies': true
My question here is how would I insert the REST module without using phpbrowser? It appears that it may be required, but does anybody know otherwise?
It is impossible - WebDriver and REST modules are incompatible.
I try to configure unit-tests suite in Codeception. When I run suite Codeception fail with error Fatal error: Cannot re-declare class rest\tests\UnitTester. With debugger I located places where it loads class first and second time.
First time Codeception load Actor in Codeception\Test\Loader\Gherkin during adding steps to loader.
Second time it initialize Actor instance for class with tests. In second place this class must be already included, but again loader is triggered. Here error appear.
Class is loaded with Codeception loader. At first I think that it was caused by namespace, but UnitTester is only one class in namespace. My .yml files a listed below. I would be very grateful for help.
codeception.yml:
actor: Tester
paths:
tests: tests
log: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs
settings:
bootstrap: _bootstrap.php
colors: true
memory_limit: 1024M
modules:
config:
Yii2:
configFile: 'config/test-local.php'
unit.suite.yml:
class_name: UnitTester
modules:
enabled:
- Yii2
- Asserts
I found a reason of this problem. My codeception.yml for this tests missing namespace param when classes in test folder was under namespace. This caused my problem.
I am using codeception 2.2.5 aand Yii 1.1.4
I have the issue with the Yii1 module. I have it configured for functional and unit tests
Here is the functional.suite.yml
class_name: FunctionalTester
modules:
enabled:
- Yii1:
appPath: 'www/test.php'
url: 'http://localhost/test.php'
part: init
- PhpBrowser:
url: 'http://localhost/index-test.php'
- \Helper\Functional
coverage:
enabled: true
remote: false
Here is the unit.suite.yml
class_name: UnitTester
modules:
enabled:
- Asserts
- Yii1:
appPath: 'www/test.php'
url: 'http://localhost/test.php'
- \Helper\Unit
When I run the tests separately everything works great. e.g.
php codecept.phar run functional --xml --html
php codecept.phar run unit --xml --html
When I run all together
php codecept.phar run --xml --html
It runs the functional without the issue connected with the Yii1 module. And on the unit it brings
[Codeception\Exception\ModuleConfigException]
Yii1 module is not configured!
Couldn't load application config file www/test.php
Please provide application bootstrap file configured for testing
The main goal to run all together is the code coverage.
Here is the answer to my problem:
I created a separate module Yii1Ext(Yii1Ext.php) which extends to Yii1 module:
namespace Helper;
use Codeception\Module\Yii1;
class Yii1Ext extends Yii1
{
public function _initialize()
{
$this->config['appPath'] = FRONTEND.'/'.$this->config['appPath'];
parent::_initialize();
}
}
And in configuration files have the Yii1Ext module enabled instead of Yii1 module
class_name: FunctionalTester
modules:
enabled:
- \Helper\Yii1Ext:
appPath: 'www/test.php'
url: 'http://localhost/test.php'
part: init
- PhpBrowser:
url: 'http://localhost/'
Note: Make sure all defined variables in Yii are defined by the statement
defined('ROOT_DIR') or define('ROOT_DIR', realpath(__DIR__ . '/../'));
Here is the code I am running:
$zf1 = $this->getModule('ZF1');
$zf1->_loadPage('POST', '/user/login', $params);
$zf1->setCookie('PHPSESSID', $zf1->grabCookie('PHPSESSID'));
The output looks like this:
[Page] /user/login
[Response] 200
[Request Cookies] []
[Response Headers] []
[Session] []
[Cookie Jar] []
[Cookie Jar] ["PHPSESSID=; path=/; httponly"]
It is displaying no headers or cookies.
I am trying to test logging into the site, get the cookie, then set the cookie to perform another action.
Also, tested using the REST module:
$this->getModule('REST')->sendPOST('/user/login', $params);
$this->debugSection('Cookies', $this->getModule('REST')->client->getCookieJar()->all());
Which also doesn't return a cookie although it has the Set-Cookie header:
[Request headers] []
[Request] POST https://www.domain.com/user/login {"email":"testing#testing.com","password":"testing"}
[Response] <html> ....html goes here..... </html>
[Headers] {"Date":["Thu, 10 Dec 2015 07:29:07 GMT"],"Server":["Apache/2.4.16 (Unix) PHP/7.0.0 OpenSSL/0.9.8zg"],"X-Powered-By":["PHP/7.0.0"],"Set-Cookie":["PHPSESSID=d8ov6rpd7ggg00npe4dinubpi7; path=/"],"Expires":["Thu, 19 Nov 1981 08:52:00 GMT"],"Cache-Control":["no-store, no-cache, must-revalidate"],"Pragma":["no-cache"],"Content-Length":["866"],"Content-Type":["text/html; charset=UTF-8"]}
[Status] 200
[Cookies] [{}]
What is going on? I am using Codeception version 2.1.4 and PHP 7. I also just tried with PHP 5.5 with the same result. And ran 'composer update' too but that didn't change anything.
codeception.yml
actor: Tester
paths:
tests: tests
log: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs
settings:
bootstrap: _bootstrap.php
suite_class: \PHPUnit_Framework_TestSuite
colors: true
memory_limit: 1024M
extensions:
enabled:
- Codeception\Extension\RunFailed
modules:
config:
Db:
dsn: 'mysql:host=127.0.0.1;dbname=somedb_test'
user: 'root'
password: ''
dump: tests/_data/dump.sql
populate: true
cleanup: false
reconnect: true
functional.suite.yml:
class_name: FunctionalTester
modules:
enabled:
- ZF1:
- Db
- \Helper\Functional
- REST:
depends: PhpBrowser
url: 'https://www.domain.com'
config:
ZF1:
env: testing
config: application/configs/application.ini
app_path: application
lib_path: library
UPDATE
Now... I'm just really confused. I am able to login but then after I try to call _request() in my helper it loses the session?? For example,
I can use $I->amOnPage(...) and it goes to the page but then I try to perform a _request(), the request call no longer has the session?
It does the following and it is clearly logged but then loses the session?:
$I->amOnPage('/');
$I->login();
$I->amOnPage('/user/questions');
$I->see('No active questions');
$I->sendPOST('/chat/upload', $params, $files);
the sendPOST is this:
$this->getModule('ZF1')->_loadPage('POST', $uri, $params, $files);
There is a similar question already posted but it's different then my problem ( Codeception: Keep a logged in state )
If I replace the sendPost with amOnPage it maintains the session (wtf???)
Apparently defining a helper method called sendPOST conflicted with the sendPOST in the REST module so it was not actually executing my code. I renamed it then it began to work. And, reported to codeception: https://github.com/Codeception/Codeception/issues/2627
I had both the ZF1 and REST module enabled in my functional.suite.yml.
In my FunctionalTester helper class in \Helper\Functional.php I had a method called sendPOST. When calling sendPOST from my *Cest class it would execute the sendPOST in the REST module. After renaming sendPOST to something else it worked.
It's true I probably don't need to load both the ZF1/REST module at the same time (still new to this codeception thing), but even so it never triggered an error that there was a duplicate sendPOST method and led to confusion. Ideally it'll throw an exception about the duplicate methods.