当存在多种情况时,Behat会挂起,但只能在一个情况下工作 [英] Behat hangs when there are multiple scenarios, but works on a single one
问题描述
我有这样写的Behat测试用例:
I have Behat test cases written like so:
Feature: Checkout
In order to buy products
As a customer
I need to be able to checkout items in the cart
Background:
Given step 1
And step 2
@Ready
Scenario: Deliver now
When step 3
Then step 4
@NoneReady
Scenario: Deliver later
When step a
Then step b
And step c
@AddressNotCovered
Scenario: Address Not Covered
When step i
Then step ii
如果我在单个标签上运行behat,它就可以正常工作:
If I run behat on a single tag, it works just fine:
$ behat --tags=Ready
Feature: Checkout
In order to buy products
As a customer
I need to be able to checkout items in the cart
@Ready
Scenario: Deliver now # tests/features/Checkout/CheckOut.feature:9
step 1
And step 2
..
1 scenario (1 passed)
7 steps (7 passed)
0m3.85s (36.62Mb)
但是,如果我在多个标签上运行它,它将挂在第一个标签的末尾:
But if I run it on multiple tags, it hangs at the end of the first tag:
behat --tags=Ready,AddressNotCovered
Feature: Checkout
In order to buy products
As a customer
I need to be able to checkout items in the cart
@Ready
Scenario: Deliver now # tests/features/Checkout/CheckOut.feature:9
Given step ..
..
And ..
// hangs here
我在做什么错了?
Laravel 5.4
Behat 3.1.0
PHP 7.1.23
PHPUnit 5.7.27
来自我的composer.json
from my composer.json
"require": {
"php": ">=5.5.9",
"laravel/framework": "5.4.*",
..
"behat/behat": "3.1.0",
"laracasts/behat-laravel-extension": "^1.1",
},
"require-dev": {
"phpunit/phpunit": "~5.7",
"phpspec/phpspec": "~2.1",
"johnkary/phpunit-speedtrap": "^1.0",
},
Behat.yml
default:
extensions:
Laracasts\Behat:
env_path: .env.testing
autoload:
- ./tests/features/bootstrap
suites:
Checkout:
paths: [./tests/features/Checkout]
contexts: [CheckoutFeatureContext]
更新
我试图创建小黄瓜来说明上述问题.尝试自动附加摘要时遇到了相同的问题.附加代码段仅适用于单个方案,但在多个方案中均不适用:
Update
I tried to create sample gherkin to illustrate the problem above. I ran into the same problem when trying to auto append snippets. Appending snippets worked with a single scenario, but failed on multiple scenarios:
# tests/features/Example/Example.feature
Feature: Example
In order to show dev team how to use behat/gherkin using background
As a developer
I need to be able write gherkin using a background and multiple scenarios
And all scenarios should run
Background:
Givens setup condition 1
And setup condition 2
Scenario: scenario one
When I perform first sample trigger point
Then result one must happen
And result two must happen
当我运行以下命令时
behat tests/features/Example/Example.feature --append-snippets
添加代码片段效果很好
Feature: Example
In order to show dev team how to use behat/gherkin using background
As a developer
I need to be able write gherkin using a background and multiple scenarios
And all scenarios should run
Background: # tests/features/Example/Example.feature:9
Givens setup condition 1
And setup condition 2
Scenario: scenario one # tests/features/Example/Example.feature:13
When I perform first sample trigger point
Then result one must happen
And result two must happen
1 scenario (1 undefined)
4 steps (4 undefined)
0m0.48s (24.63Mb)
u tests/features/bootstrap/FeatureContext.php - `setup condition 2` definition added
u tests/features/bootstrap/FeatureContext.php - `I perform first sample trigger point` definition added
u tests/features/bootstrap/FeatureContext.php - `result one must happen` definition added
u tests/features/bootstrap/FeatureContext.php - `result two must happen` definition added
失败的例子:多种情况
当我们有多种情况时
failing example: multiple scenarios
when we have multiple scenarios
# tests/features/Example/Example.feature
Feature: Example
In order to show dev team how to use behat/gherkin using background
As a developer
I need to be able write gherkin using a background and multiple scenarios
And all scenarios should run
Background:
Givens setup condition 1
And setup condition 2
Scenario: scenario one
When I perform first sample trigger point
Then result one must happen
And result two must happen
Scenario: scenario two
When I perform second sample trigger point
Then result a must happen
And result b must happen
运行相同的--append-snippets命令扼流圈:
running the same --append-snippets command chokes:
Feature: Example
In order to show dev team how to use behat/gherkin using background
As a developer
I need to be able write gherkin using a background and multiple scenarios
And all scenarios should run
Background: # tests/features/Example/Example.feature:9
Givens setup condition 1
And setup condition 2
Scenario: scenario one # tests/features/Example/Example.feature:13
When I perform first sample trigger point
Then result one must happen
And result two must happen
^C // had to abort here
推荐答案
事实证明,以上示例过于简单.经过一些研究(这篇文章特别有用),我意识到这是停滞"是由于每次测试后都删除了数据库.所以这是解决问题的方法:
It turns out the examples above were too simplistic. After doing some research (especially helpful was this post) I realized that this "stalling" is due to tearing down the database after each test. So this is what fixed it:
首先,我在FeatureContext类中将DatabaseTransactions
替换为DatabaseMigrations
:
First I replaced DatabaseTransactions
with DatabaseMigrations
in my FeatureContext class:
class FeatureContext extends TestCase implements Context, SnippetAcceptingContext
{
use DatabaseMigrations, ..
鉴于上述情况,我从位桶管道脚本中删除了手动迁移命令
Given the above, I removed the manual migration comand from my bitbucket pipeline script
- php artisan --env=testing config:cache
这是有道理的,因为有了新代码,数据库将始终在每次测试之前进行刷新和迁移.
which makes sense since with the new code, the database will always be refreshed and migrated before each test.
然后我将setUp()
调用添加到 behat钩子:
/** @BeforeScenario */
public function before(BeforeScenarioScope $scope)
{
parent::setUp();
}
就是这样.关于此解决方案的最好之处在于,它使我的本地测试环境与Bitbucket管道完全一致,因此结果始终是相同的.
And that's it. The best part about this solution is that it completely aligned my local testing environment with that of bitbucket pipelines, so that the results were always the same.
通常,最好重新启动每个测试,而又不要遗漏以前的测试(尤其是数据库). 用laravel的话:
In general, it's a good idea to start each test fresh without left overs from the previous test (esp when it comes to databases). In the words of laravel:
每次测试后重置数据库通常很有用,这样数据 来自先前测试的内容不会干扰后续测试.
It is often useful to reset your database after each test so that data from a previous test does not interfere with subsequent tests.
为此,我们使用迁移.话虽这么说,因为我们实际上是在使用Behat,所以我们需要在每个场景生命周期之前和之后进行迁移.我们使用 Behat's hooks 来做到这一点.我们在这里这样做:
For that we use migrations. That being said, since we're actually using Behat, we need this migration to happen before and after each scenario life cycle. We do that using Behat's hooks. We do that here:
/** @BeforeScenario */
public function before(BeforeScenarioScope $scope)
{
parent::setUp();
}
parent::setUP()
告诉 Laravel框架在每种情况之前和之后都要做必要的工作:
parent::setUP()
tells the Laravel framework to do the necessary work before and after each scenario:
protected function setUp()
{
if (! $this->app) {
$this->refreshApplication();
}
$this->setUpTraits(); <---- here
..
这又称为设置特征:
protected function setUpTraits()
{
$uses = array_flip(class_uses_recursive(static::class));
if (isset($uses[DatabaseMigrations::class])) {
$this->runDatabaseMigrations();
}
..
将其称为
public function runDatabaseMigrations()
{
$this->artisan('migrate:fresh');
$this->app[Kernel::class]->setArtisan(null);
$this->beforeApplicationDestroyed(function () {
$this->artisan('migrate:rollback');
RefreshDatabaseState::$migrated = false;
});
}
请注意,一旦应用程序被销毁,Laravel也将回滚更改.理解这一点非常重要,以防止在存在多个场景和特定场景的情况下Behat停止运行.另外请记住,当我们像这样使用小黄瓜时:
Notice that Laravel will also rollback the changes once the application is destroyed. It's very important to understand this in order to prevent Behat stalling when there are multiple scenarios and a given before them. Also keep in mind that when we use Gherkin like so:
Feature: Checkout
In order to buy products
As a customer
I need to be able to checkout items in the cart
Background:
Given step 1
And step 2
@Ready
Scenario: Deliver now
When step 3
Then step 4
@NoneReady
Scenario: Deliver later
When step a
Then step b
And step c
然后每个方案都从后台步骤开始,而不是在方案步骤本身中
Then each scenario starts with the background steps, not in the scenario steps itself
示例:
Feature: Checkout
In order to buy products
As a customer
I need to be able to checkout items in the cart
Background:
Given step 1 <-- every scenario starts here, so we call setup before this step
And step 2
@Ready
Scenario: Deliver now
When step 3 <-- not here
Then step 4
@NoneReady
Scenario: Deliver later
When step a
Then step b
And step c
这篇关于当存在多种情况时,Behat会挂起,但只能在一个情况下工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!