Codeception Cept tests _bootstrap variables - codeception

Codeception default _bootstrap.php file states:
<?php
// Here you can initialize variables that will be available to your tests
So I wanted to initialize a variable inside of it:
<?php
$a = 5;
However, when I use it my SomeAcceptanceCept:
<?php
// ....
$I->fillField('description', $a);
I get: ErrorException: Undefined variable: a
I did var_dump in _bootstrap.php and it indeed get's ran once before acceptance tests, but variables from it are not available in my tests.
I can't seem to find any documentation on this.
I'm actually trying to initialize Faker instance to use in my tests.

I find the documentation on this to be quite confusing. I was attempting to do the exact same thing to no avail. So I ended up using Fixtures by putting this in the _bootstrap.php file:
use Codeception\Util\Fixtures;
use Faker\Factory;
$fake = Factory::create();
Fixtures::add('fake', $fake);
(You could also use a separate fixtures.php file and include it in your test.)
Which allows you to get the faker object or anything else like this:
Fixtures::get('fake');
The strange thing is that if you look at the Fixtures docs it actually mentions using the Faker library to create tests data in the bootstrap file.

I do the following:
// _bootstrap.php
$GLOBALS['a'] = 5;
Then within my tests I call it like so:
// MyCest.php
public function testItWorks(\Tester $I)
{
global $a;
$I->fillField('description', $a);
}
I haven't done much work with Cept files but probably something similar will work.

Define it like this in your bootstrap.php :
<?php
// This is global bootstrap for autoloading
define("email", "someone#abc.com");
define("password", "my_secure_pass")
Use it like this:
public function testValidLogin(AcceptanceTester $I)
{
$I->fillField(loginPage::$username, email);
$I->fillField(loginPage::$password, password);
$I->click("LOG IN");
}
NOTE: no dollar signs. use as only as 'email' and 'password'

I dumped all PHP variables and confirmed that any variables set in the _bootstrap.php file do not exist and are not available in the MyCept.php file. So I resorted to adding the following at the top of MyCept.php:
include '_bootstrap.php';
This makes the variables set in _bootstrap.php available. Of course.

Related

How to use module.exports and requireJS?

im quite a noob in html and js, so forgive me if this is a dumb question but, im trying to use requireJs to export modules in node and i can't get the function work right.
here is the code extracted from example.
first i have this main.js, as the note in the documentation says http://requirejs.org/docs/node.html#2
var sayHi = require(['./greetings.js'], function(){});
console.log(sayHi);
and a greetings.js who export the answer
module.exports= 'Hello';
});
and get nothing as result, so i define the exports and modules
define( function(exports,module){
module.exports= 'Hello';
});
and get as result:
function localRequire()
what am i doing wrong? i read the documentation and examples, but somehow i can't make this works.
I'm assuming the require call you are using is RequireJS's require call, not Node's require. (Otherwise, you'd get a very different result.)
You are using the asynchronous form of the require call. With the asynchronous form, there is no return value for you to use, you have to use the callback to get module values, like this:
require(['./greetings.js'], function(sayHi){
console.log(sayHi);
});
However, because you are running in Node, you can do this:
var sayHi = require('./greetings.js');
Note how the first argument is a string, not an array of dependencies. This is the synchronous form of the require call. The returned value is the module you required. When you are in Node, RequireJS allows you to call this synchronous form anywhere. When you are running the browser, it is only available inside a define call.

Code coverage in SimpleTest

Is there any way to generate code coverage report when using SimpleTest similar to PHPUnit.
I have read the documentation of SimpleTest on their website but can not find a clear way on how to do it!
I came across this website that says
we can add require_once (dirname(__FILE__).'/coverage.php')
to the intended file and it should generate the report, but it did not work!
If there is a helpful website on how to generate code coverage, please share it here.
Thanks alot.
I could not get it to work in the officially supported way either, but here is something I got working that I was able to hack together by examining their code. This works for v1.1.7 of SimpleTest, not their master code. At the time of this writing v1.1.7 is the latest release, and works with new versions of PHP 7, even though it is an old release.
First off you have to make sure you have Xdebug installed, configured, and working. On my system there is both a CLI and Apache version of the php.ini file that have to be configured properly depending on if I am trying to use PHP through Apache or just directly from the terminal. There are alternatives to Xdebug, but most people us Xdebug.
Then, you have to make the PHP_CodeCoverage library accessible from your code. I recommend adding it to your project as a composer package.
Now you just have to manually use that library to capture code coverage and generate a report. How exactly you do that will depend on how you run your tests. Personally, I run my tests on the terminal, and I have a bootstrap file that php runs before it starts the script. At the end of the bootstrap file, I include the SimpleTest autorun file so it will automatically run the tests in any test classes that get included like so:
require_once __DIR__.'/vendor/simpletest/simpletest/autorun.php';
Somewhere inside your bootstrap file you will need to create a filter, whitelist the directories and files you want to get reported, create a coverage object and pass in the filter to the constructor, start coverage, and create and register a shutdown function that will change the way SimpleTest executes the tests to make sure it also stops the coverage and generates the coverage report. Your bootstrap file might look something like this:
<?php
require __DIR__.'/vendor/autoload.php';
$filter = new \SebastianBergmann\CodeCoverage\Filter();
$filter->addDirectoryToWhitelist(__DIR__."/src/");
$coverage = new \SebastianBergmann\CodeCoverage\CodeCoverage(null, $filter);
$coverage->start('<name of test>');
function shutdownWithCoverage($coverage)
{
$autorun = function_exists('\run_local_tests'); // provided by simpletest
if ($autorun) {
$result = \run_local_tests(); // this actually runs the tests
}
$coverage->stop();
$writer = new \SebastianBergmann\CodeCoverage\Report\Html\Facade;
$writer->process($coverage, __DIR__.'/tmp/code-coverage-report');
if ($autorun) {
// prevent tests from running twice:
exit($result ? 0 : 1);
}
}
register_shutdown_function('\shutdownWithCoverage', $coverage);
require_once __DIR__.'/vendor/simpletest/simpletest/autorun.php';
It took me some time to figure out, as - to put it mildly - the documentation for this feature is not really complete.
Once you have your test suite up and running, just include these lines before the lines that are actually running it:
require_once ('simpletest/extensions/coverage/coverage.php');
require_once ('simpletest/extensions/coverage/coverage_reporter.php');
$coverage = new CodeCoverage();
$coverage->log = 'coverage/log.sqlite'; // This folder should exist
$coverage->includes = ['.*\.php$']; // Modify these as you wish
$coverage->excludes = ['simpletest.*']; // Or it is even better to use a setting file
$coverage->maxDirectoryDepth = '1';
$coverage->resetLog();
$coverage->startCoverage();
Then run your tests, for instance:
$test = new ProjectTests(); //It is an extension of the class TestSuite
$test->run(new HtmlReporter());
Finally generate your reports
$coverage->stopCoverage();
$coverage->writeUntouched();
$handler = new CoverageDataHandler($coverage->log);
$report = new CoverageReporter();
$report->reportDir = 'coverage/report'; // This folder should exist
$report->title = 'Code Coverage Report';
$report->coverage = $handler->read();
$report->untouched = $handler->readUntouchedFiles();
$report->summaryFile = $report->reportDir . '/index.html';
And that's it. Based on your setup, you might need to make some small adjustment to make it work. For instance, if you are using the autorun.php from simpletest, that might be a bit more tricky.

What is the purpose, and proper use of wantTo() in Codeception?

I'm using the testing framework Codeception to do BDD. I understand the idea of wanting something, but I don't understand what the function does.
$I->wantTo('Understand what this method does!');
http://codeception.com/docs/03-AcceptanceTests#Comments
Commands like amGoingTo, expect, expectTo help you in making tests
more descriptive.
$I->wantTo('Understand what this method does!');
will be rendered as * I want to understand what this method does! in verbose output.
Update 2022-11-16:
My original answer was incorrect, wantTo is not a comment method, it renames test method in the output.
Example:
I created very simple Cest class:
<?php
class ExampleCest
{
public function provideExample(CliGuy $I)
{
}
}
When I ran it, I got the following output:
Cli Tests (1) --------------------------------------------
U ExampleCest: Provide example (0.00s)
---------------------------------------------------------
but after adding $I->wantTo('change test name!'); to method:
I got the following output:
Cli Tests (1) --------------------------------------------
U ExampleCest: Change test name! (0.00s)
---------------------------------------------------------
The benefit of wantTo is that it allows to use characters not permitted in method names or different formatting than automatically generated.
I looked up if wantTo has any documentation and all I found was old blog post using examples in class-less Cept format (which is deprecated and is likely to be removed in Codeception 6).
<?php
$I = new TestGuy($scenario);
$I->wantTo('log in to site');
$I->amOnPage('/');
$I->click('Login');
$I->fillField('username', 'admin');
In Cept format wantTo had better purpose, because it didn't override anything, but provided additional information next to file name.

How can I target a test in the _before() hook

I have a Codeception cest file which has a number of tests in it.
In some of the tests, there are initializations which I would like to so in the _before() hook. These initializations are specific to those tests only and to no other test in the cest file.
How can I go about this?
The pseudocode would be something like
public _before($event)
{
if ($event->test_being_run == 'testThatFeature')
{
$init = something(here);
}
}
Through investigation, I have realized that the $event variable passed into the _before() hook is an instance of the generated AcceptanceTester; as opposed to \Codeception\Event\TestCase. So I cannot use the hopeful $event->getTest()->getTestFullName().
Codeception injects parameters based on type hinting.
If you want to get \Codeception\Event\TestCase, your code must look like this:
public _before(\Codeception\Event\TestCase $event)
All information that I found about receiving testcase in _before method, was about _before method of modules and extensions, it does not apply to tests.
If you want to run specific code for one test, just run it in the test code.

Protractor - How to separate each test to one file and separate variabiles

I have some komplex protractor test written but everything is in one file.
Where I'm on top of it loading all variabiles like:
var userLogin = "John";
and after that somewhere in code I use it together.
What I need to do is
1. Separate all variabiles to aditional file (some config file)
2. Each test to one file
1- I try to make config.js where I add all variabiles and i required it in protractor.conf.js it load correctly problem is that when i use any of this variabiles in some test it's not working (test fail with "userName is not defined")
I know there is a way where i requre config.file in each test script but that's really not best option in my eyes.
2- How can I know what I did in last script if it's separate, like for example how to know I am logged in?
Thanks.
There are multiple things you can make use of.
2) How can I know what I did in last script if it's separate, like for example how to know I am logged in?
This is where beforeEach(), afterEach() can help:
To help a test suite DRY up any duplicated setup and teardown code,
Jasmine provides the global beforeEach and afterEach functions. As the
name implies, the beforeEach function is called once before each spec
in the describe is run, and the afterEach function is called once
after each spec.
There are also beforeAll(), afterAll() available in jasmine 2, or via jasmine-beforeAll third-party for jasmine 1:
The beforeAll function is called only once before all the specs in
describe are run, and the afterAll function is called after all specs
finish. These functions can be used to speed up test suites with
expensive setup and teardown.
1) I try to make config.js where I add all variabiles and i required
it in protractor.conf.js it load correctly problem is that when i use
any of this variabiles in some test it's not working (test fail with
"userName is not defined") I know there is a way where i requre
config.file in each test script but that's really not best option in
my eyes.
One option which I've personally used would be to create a config.js file with all the reusable configuration variables you would need in multiple tests and require the file once - in the protractor config - then set it as a params configuration key value:
var config = require("./config.js");
exports.config = {
...
params: config,
...
};
where config.js is, for example:
var config;
config = {
user: {
login: "user",
password: "password"
}
};
module.exports = config;
Then, you would not need to require config.js in every test, but instead, you'll use browser.params. For example:
expect(browser.params.user.login).toEqual("user");
Also, if you need some sort of a global test preparation step, you can do it in onPrepare() function, see Setting Up the System Under Test. Example configuration that performs a "global" login step is available here.
And an another quick note: you can have custom globally defined variables (like built-in browser or protractor), set them using global in onPrepare. For example, I've defined protractor.ExpectedConditions as a custom global variable:
onPrepare: function () {
global.EC = protractor.ExpectedConditions;
}
Then, in tests, don't require anything, `EC variable would be available in the scope, e.g.:
browser.wait(EC.invisibilityOf(scope.page.dropdown), 5000)
Also, organizing your tests using "Page Object Pattern" would also help to solve the reusability and modularity problem.