Behave: How to set a timeout to abort single scenario inside an Scenario Outline

92 Views Asked by At

Due environment related issues (it's not the case here) some scenarios take longer than expected or "hangs" forever. Then I need to abort that single scenario and continue with the rest.

I tried using fixtures or with an approach similar to runner.abort_by_user.feature with no luck but.

I'm able to abort the test but it breaks the whole execution and that is something that I want to avoid. Also I found no way to set a timeout per Scenario.

Schematically my scenario is:

feature file

Feature: ...
  Background: ...
    Given ...
  Scenario Outline: ...
    Given ...
    When  ...
    Then  ...
  Examples: A
    | a | b | c |
    ...
    | x | y | z |
    
  
  Scenario Outline: ...
    Given ...
    When  ...
    Then  ...
  Examples: B
    | a | b | c |
    ...
    | x | y | z |

What I want is:

  • Place a timeout (somehow) to allow me detect and abort a single scenario
  • The rest of scenarios should keep running
  • The next of "Scenarios Outlines" should keep running too
1

There are 1 best solutions below

1
On

Here you have an example of an solution that will not stop the execution of any test, but it will identify if a test is taking so long:

test.feature

Feature: Timeout Tests

Scenario Outline: Test with timeout Given Start the test with a timeout of "" sec And This step lasts 10 second Examples: | TIMEOUT | | 8 | | 12 |

environment.py

import datetime


def after_step(context, step):
    comparison = datetime.datetime.now() - context.start_time
    if comparison.total_seconds() > int(context.timeout):
        assert False, "TIMEOUT REACHED"

common_steps.py

import time
from datetime import datetime

from behave import step


@step(u'Start the test with a timeout of "{timeout}" sec')
def step_impl(context, timeout):
    print(f"Starting the test with a timeout of {timeout} seconds")
    # Store the current time
    context.start_time = datetime.now()
    context.timeout = timeout


@step(u'This step lasts 10 second')
def step_impl(context):
    time.sleep(10)

Explanation

At the begining of the test, we store the current time. Then, after each step we check if a timeout is reached. Take care because if some step never ends, or it takes (for instance) 20 minutes to execute, this solution will not be able to detect the timeout consumtion until those 20 minutes.