-
Notifications
You must be signed in to change notification settings - Fork 40
Test dependencies
Test dependencies is basically something you want to avoid - it for example violates the FIRST principle and also limits possibility of parallelization.
However, there are certain scenarios in end-to-end tests, when dependency between two tests (or two phases of one tests) may actually occur. For example:
- You add some item into database, and it takes some time until it is indexed by your fulltext engine, so you can verify the newly added item could be found through the search
- Your app sends an e-mail (eg. with password reset link) and you want to check this email on IMAP server to verify the reset link works as intended
- Seeding test fixtures (base data) for your functional tests is time/resources consuming, so you eg. create one user on beginning of your test suite and reuse this user in all other tests requiring an user data.
a) The dependency is just because of order of the test methods (one test must run before the other one) and limited to one test-case class (and you don't need to wait between the two dependent tests). In this case you can use PHPUnit's @depends
annotation - see below.
b) You either need to wait some time before tests or the dependency involves more then one test-case, Steward provides a simple way how to define the dependency - you just define @delayAfter
and @delayMinutes
annotations for the test-case class which is depending on some other class. See below for more information and example usage.
First test (to be run before the SecondTest
test-case):
<?php
namespace My;
class FirstTest extends \Lmc\Steward\Test\AbstractTestCase
{
public function testSomething()
{
...
}
}
SecondTest
will be run only after FirstTest (successfully) finishes and after defined delay (1.5 minute) passes:
<?php
namespace My;
/**
* @delayAfter My\FirstTest
* @delayMinutes 1.5
*/
class SecondTest extends \Lmc\Steward\Test\AbstractTestCase
{
public function testSomething()
{
...
}
}
To enable this dependency, add these annotations to the test which is depending on other test:
-
@delayAfter
- contains fully qualified name of the test-case it depend on, likeFoo\Bar\MyTest
-
@delayMinutes
(float) - delay in minutes after which this test-case should be run after the test-case defined in@delayAfter
; could be also0
or floating value like0.1
(= 6 seconds)
During development/debugging, you may want to run just the test, which is depending on some other test. To force Steward to ignore dependencies between test-cases (defined using @delayAfter
and @delayMinutes
annotations), pass to the run command option --ignore-delays
(or -i
).
# run DelayedExampleTest.php even if it is depending on some other tests
$ steward run dev firefox --pattern DelayedExampleTest.php --ignore-delays
You may also want to store some data in first test and use them in any depending test-case. For this purpose Steward contains component called Legacy.
<?php
namespace My;
use Lmc\Steward\Component\Legacy;
class FirstTest extends \Lmc\Steward\Test\AbstractTestCase
{
/** @var Legacy */
private $legacy;
/** @before */
public function init()
{
// initialize the Legacy component before the test
$this->legacy = new Legacy($this);
}
public function testSeedSomeData()
{
// In real-world we could eg. create some fixture objects on our site etc.
$data = ['name' => 'Foo Bar', 'phone' => '123 456 789'];
...
$this->legacy->saveWithName($data, 'identifier-of-the-data-seed');
}
}
Now in the dependent test-case we can load the data like this:
<?php
namespace My;
use Lmc\Steward\Component\Legacy;
/**
* @delayAfter My\SeedDataTest
* @delayMinutes 1.5
*/
class SecondTest extends \Lmc\Steward\Test\AbstractTestCase
{
/** @var array */
private $data;
/** @before */
public function init()
{
// Load the data created and stored by the previous test (note we must use the same identifier)
$this->data = (new Legacy($this))->loadWithName('identifier-of-the-data-seed');
}
public function testSomething()
{
// we can now access the data like: $this->data['name'];
...
}
}