首页 > 解决方案 > 通过 webdriver.io 运行时,如何找到失败的 cucumber-js 步骤的行号?

问题描述

我最近从一个非常旧版本的 cucumber-js (4.2.1) 升级到一个更新的版本 (7.2.1),我似乎失去了判断我的功能文件中哪一行测试失败的能力。我通过 Webdriver.io (v7.7) 使用黄瓜。我有一个这样的测试:

  Scenario: I am testing some things. # <-- line 361
    Given I login
    #... <a bunch of more steps>
    Then I verify there's an error message exactly as   # <-- line 580
    """
    You cannot modify a requirement in the system that belongs to an archived process.
    """
    #... more steps

当我运行测试但它失败时(这是合法的,因为我不小心弄坏了一些东西),我看到来自spec记者的错误,例如:

[chrome 92.0.4515.159 windows #0-0] 167 passing (5m 22.9s)
[chrome 92.0.4515.159 windows #0-0] 1 failing
[chrome 92.0.4515.159 windows #0-0] 38 skipped
[chrome 92.0.4515.159 windows #0-0]
[chrome 92.0.4515.159 windows #0-0] 1) I am testing some things. Then I verify there's an error message exactly as
[chrome 92.0.4515.159 windows #0-0] Error: expect(received).toBe(expected) // Object.is equality
[chrome 92.0.4515.159 windows #0-0] Error: expect(received).toBe(expected) // Object.is equality
[chrome 92.0.4515.159 windows #0-0]
[chrome 92.0.4515.159 windows #0-0] Expected: "You cannot modify a requirement in the system that belongs to an archived process."
[chrome 92.0.4515.159 windows #0-0] Received: ""
[chrome 92.0.4515.159 windows #0-0]     at World.<anonymous> (C:\projects\qbdvision\build\test\features\step_definitions\common_steps.js:196:51)
[chrome 92.0.4515.159 windows #0-0]     at runMicrotasks (<anonymous>)
[chrome 92.0.4515.159 windows #0-0]     at processTicksAndRejections (internal/process/task_queues.js:95:5)
[chrome 92.0.4515.159 windows #0-0]     at World.executeAsync (C:\projects\qbdvision\node_modules\@wdio\cucumber-framework\node_modules\@wdio\utils\build\shim.js:136:16)
[chrome 92.0.4515.159 windows #0-0]     at World.testFrameworkFnWrapper (C:\projects\qbdvision\node_modules\@wdio\cucumber-framework\node_modules\@wdio\utils\build\test-framework\testFnWrapper.js:52:18)

如何确定我的场景 (:361) 或我的步骤 (:580) 在哪个行号上?

我曾经在 Cucumber-js 4.2.1 中看到过这样的错误:

Failures: 
  
 1) Scenario: I am testing some things. - build/test/features/my_feature.feature:361 
    Step: Then I verify there's an error message exactly as - build/test/features/document/my_feature.feature:580 
    Step Definition: build/test/features/step_definitions/common_steps.js:23 
    Message: 
        Expected: "You cannot modify a requirement in the system that belongs to an archived process."
        Received: ""
            at World.<anonymous> (C:\projects\qbdvision\build\test\features\step_definitions\common_steps.js:196:51)
            at runMicrotasks (<anonymous>)
            at processTicksAndRejections (internal/process/task_queues.js:95:5)
            at World.executeAsync (C:\projects\qbdvision\node_modules\@wdio\cucumber-framework\node_modules\@wdio\utils\build\shim.js:136:16)
            at World.testFrameworkFnWrapper (C:\projects\qbdvision\node_modules\@wdio\cucumber-framework\node_modules\@wdio\utils\build\test-framework\testFnWrapper.js:52:18)
  
 3 scenarios (1 failed, 2 passed) 
 188 steps (1 failed, 15 skipped, 172 passed) 
 4m57.582s 

如何恢复该功能?

标签: node.jswebdriver-iocucumberjs

解决方案


我发现查看行号的技巧通常在格式化程序中,我似乎无法从我的wdio.conf.js文件中设置。

我通过将其添加到我的wdio.conf.js

export.config = {
  ... // other stuff
  /**
   *
   * Runs after a Cucumber Step.
   * @param {Pickle.IPickleStep} step     step data
   * @param {IPickle}            scenario scenario pickle
   * @param {Object}             result   results object containing scenario results
   * @param {boolean}            result.passed   true if scenario has passed
   * @param {string}             result.error    error stack if scenario failed
   * @param {number}             result.duration duration of scenario in milliseconds
   */
  afterStep: async function(step, scenario, result) {
    if (!result.passed) {
      // Keep track of the failed step & scenario so we can print it out below.
      global.failedStepId = step.astNodeIds[0];
    }
  },

  /**
   *
   * Runs before a Cucumber Scenario.
   * @param world world object containing information on pickle and test step
   * @param result result object containing
   * @param result.passed   true if scenario has passed
   * @param result.error    error stack if scenario failed
   * @param result.duration duration of scenario in milliseconds
   */
  afterScenario: async function(world, result) {
    if (!result.passed) {
      const feature = world.gherkinDocument.feature;
      const docChildren = feature.children;

      try {
        // Find the scenario and step
        let scenario;
        let step;
        for (const docChild of docChildren) {
          let possibleScenario = docChild.scenario ? docChild.scenario : docChild.background;
          // Find the step in the scenario
          for (const possibleStep of possibleScenario.steps) {
            if (possibleStep.id === global.failedStepId) {
              step = possibleStep;
              scenario = possibleScenario;
              break;
            }
          }
          if (step) {
            break;
          }
        }
        if (!scenario || !step) {
          console.log("Error is coming from an unknown location in the gherkin feature file.");
        } else {
          console.log(`Error found in ${feature.name}:`);
          console.log(`\t${scenario.keyword}: ${scenario.name} (:${scenario.location.line})`);
          console.log(`\tStep: ${step.keyword} ${step.text} (:${step.location.line})`);
        }
      } catch (error) {
        console.error("CAUGHT ERROR WHILE TRYING TO PRINT LINE NUMBER:", Log.error(error));
      }
    }
  }
}

推荐阅读