当存在多种情况时,Behat会挂起,但只能在一个情况下工作 [英] Behat hangs when there are multiple scenarios, but works on a single one

查看:114
本文介绍了当存在多种情况时,Behat会挂起,但只能在一个情况下工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样写的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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆