How to share state between scenarios using cucumber

戏子无情 提交于 2019-11-30 15:02:36

This is intentionally very difficult to do! Sharing state between tests is generally a Very Bad Thing, not least because it forces your tests to run in sequence (your first scenario MUST run before the subsequent ones, not something Cucumber supports explicitly).

My suggestion would be to re-think your testing strategy. Hitting external services in tests is a great way to make them run slowly and be unreliable (what happens when the external service goes down?). In this case I'd suggest using something like webmock or vcr to create a fake version of the external site, that returns the same response as you'd expect from the real site, but you can hit as many times as you like without the worry of performance or unavailability.

I found that it is technically possible to use

@@global_variable in step definition to share the global state.

However, just like other people points, it may not be a good idea.

I tried to avoid repeated login steps in the similar scenarios. Again, it may not be a good practice. Use the trick when really necessary

You shouldn't share state between scenarios. A scenario describes a piece of the intended behavior for the whole system, and it should be possible to run just one scenario. E.g. if you have run the entire test suite, and you find that a single scenario fails, you should be able to run just that one scenario in order to investigate what went wrong.

Your problem arises because you try to contact external systems. That is not advisable. Not only does it make you test suite run more slowly, but it also makes the test dependent on the external system, to which you have no control. If the external system is not running, your tests are not running. If the external tests does not contain the data you expect, your tests will fail, even though there are no bugs in your own system. And you end up letting your tests be controlled by what you expect to be in the external systems, instead of controlling what is in the external system based on what you need to test.

Instead you should mock out the external system, and let your scenarios control what the mocked system will deliver:

Scenario: Query external system
    # These two lines setup expected data in a mocked version of the external system
    Given there the system x contains an article named "y"
    And the article contains the text "Lorep ipsum"
    When I query for article "y"
    Then I should see the text "Lorem ipsum"

This scenario is independent of any actual data in external systems, as it explicitly specifies what needs to be there. And more importantly, it clearly describes how your own system should behave.

The scenario in that form can also be communicated to stakeholders, and they can validate the scenarios without any prior knowledge to any test data present in those external systems.

It may take some time getting a proper framework running, but in the end, it will be worth it.

I use a file. I have a case to create a new user, then I want to logout and log back in with that same user in other features.

I generate the user with:

@randomName = [*('a'..'z')].sample(8).join

Then I save the user to a file:

File.open("randomName.txt", 'w') {|f| f.write("#{@randomName}") }

Later, when I need that data in other feature, I use:

@randomName = data = File.read("randomName.txt")

Making scenario dependent or sharing the data between scenarios is not a good practice.

some solutions 1) Cucumber provide Background tag to run preconditions for each scenario.

2) Cucumber provides hooks @Before and @after which can be customized for each scenario.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!