Closed learner010 closed 9 years ago
@learner010 'given' (I'm not sure only those) steps are also pytest fixtures by default so they are registered with their name so then you can use them as argument to any pytest test function (look at pytest-bdd examples). This makes impossible to use the same name twice (at least for given steps).
That's right. And I wonder what is the use-case of making all given steps having the same name. If they are applying the side-effect only? I believe there is a case when some other when/then step would need the value returned by a given step. This is the exchange of the information via the pytest request as a context.
I personally feel it very confusing. It might be useful in some context. At present, I create a scope fixture and attach every new values to it and pass it around. I am new to pytest and pytest-bdd. I would love to learn about the best practice for fixture.
Below is how I am handling the scope:
scenarios('../features/prepare_request.feature')
@pytest.fixture(scope='function')
def scope():
class Scope(object):
pass
return Scope()
@given('a url')
def set_url(scope):
scope.url = 'http://awesome.com'
@given('method is GET')
def set_method(scope):
scope.method = 'get'
@when('the function is called with the url and method')
def make_the_request(scope):
scope.request = make_request(scope.url, scope.method)
@then('the function should return the tuple with an instance of requests.Request')
def check(scope):
assert type(scope.request) == requests.Request
PyTest request is the scope. Fixtures are variables of this context. It seems you are using BDD with very deep detailization as a script. But still it is possible to give some fixtures values with the step. What's your full .feature file? I wonder how you are using it
For example if you are implementing primitives such as method fixture:
Given the method is "GET"
@given(parsers.parse('the method is "{method}"'))
def set_method(method):
return method
You see - the step argument is also a fixture. So you will be able to use it in the further steps:
@when('the function is called with the url and method')
def make_the_request(url, method):
scope.request = make_request(url, method)
@given(parsers.parse('the method is "{method}"'))
def set_method(method):
"""Will also work without returning any value for the set_method fixture. Method fixture is enough."""
P.S. Gherkin is for the just-enough specificaiton. It seems you are specifying what the request will be. In fact the only input which is needed is the URL and the method. Request is just an intermediate step to get the result. So I'd advice you to write when step where you rather fetch the result. Otherwise it all seems programming python in text files instead specifying the behavior, which is a lot higher level.
Feature: Request a URL
Scenario: Makes GET request to a URL
Given a url
And method is GET
When the function is called with the url and method
Then the function should return the tuple with an instance of requests.Request
The feature is something like this. I dont think we can extract object instance from scenario as u did with {method} above. I am still learning BDD, might be my approach is too verbose or too immature. Any suggestion is appreciated. :)
I believe you should specify the behavior of your entities. It looks you are testing some API. This API perhaps implements some resources, some entities. It could be CRUD or REST whatever, but the bit or URL probably identifies the resource.
Lets imagine your resource is a Book (in the Library API).
Feature: Library API Book CRUD
Scenario: Get a book
Given there's a book # In fact can apply some side effect and insert the book in the database
And the book title is "BLA"
When I get the book # This performs a GET call with the url that includes the resource id mentioned in given
Then the response book titile should be "BLA"
I know ppl used rest navigator instance as a fixture and the result of the request was cached there so you can always access it. You can still store your result in the dict fixture like you did with the context. The problem is that pytest request is the context and should be rather computed and returned than mutated and passed along.
Gherkin should specify your system. Not be a script language. You should mention concrete resources and the actions on them. Gherkin should reflect the semantics of your system, describe it, but not to script it as get/post with the parameters.
Anyway, I think this issue can be closed becuase this probably wont be implemented anyway, right? @learner010 I think if you want this feature, simplest thing is to write simple DSL (like python konira project did).
ya thanx :)
How can I use same name for all the steps? I feel the function names are meaningless once they are decorated by
@given, @then, @when
. When I name all the steps to '', I get `Fixture already in useexception. How can I instruct
pytest-bdd` not to consider steps as fixture?