Closed hans-d closed 9 years ago
Hi Hans,
I'll have a think about it. I assume the intention is to get to a known point in some workflow without having to repeatedly specify the same block of steps? In the meantime you could probably achieve something like this by passing the yadda object to the scenarios via the context. Then inside your "Background A" step, invoke yadda with some text. e.g.
describe('Yadda', function() {
it('should interpret backgrounds', function() {
var library = new Yadda.localisation.English()
.given('background $id', function(id) {
this.yadda.yadda(load_background(id));
})
.define('Log $id', function(text) {
console.log(text);
});
var yadda = new Yadda.Yadda(library);
yadda.yadda('Given background A', { yadda: yadda });
});
function load_background(id) {
return ['Log X', 'Log Y', 'Log Z']; // TODO fs.readFileSync...
};
});
The above doesn't handle circular references though (and probably violates the "Clear not Clever" principle). The better solution would be to extend the FeatureParser to be passed a set of backgrounds and to substitute them, as they are encountered.
Yes, it certainly is to get to known starting point in a DRY way. But also to specify that same background in the feature file almost like a scenario but only using Given, eg
Feature: X
Background: Generic
Given a fake zookeeper instance
With value "X" at "/some/location"
Background: Special B
Given starting situation "Generic"
With value "Y" at "/some/other/location"
Background: Special situation C
Given value "Z" at "/overhere"
Scenario: A
Given "Generic" background
And a client doing ....
...
Scenario: B
Given situation "Special B"
....
Scenario: C
Given "Generic" situation
With "Special C" situation
...
Note that Background could also be named differently, eg Situation, or even perhaps Scenario (but only the givens will be included). The inclusion would be something that can be formulated in the library, and would insert the steps at that point in the scenario.
How about adding the Background tag (which should be localisable) into a separate file, eg. common.backgrounds. Then they could be shared by multiple features. I'd create a BackgroundParser to parse the backgrounds and check for circular references, then pass the backgrounds to the FeatureParser. The Feature parser would substitute the background steps automatically when it encountered a matching given step, and return the "expanded" scenario, exactly as if you had written the scenario out in full. I'd update the mocha plugins so the test looked like...
background('./backgrounds/common.background', function(background) {
feature('./featues/zookeeper.feature', function(feature) {
scenarios(feature.scenarios, function(scenario, done) {
var yadda = new Yadda.Yadda(library);
yadda.yadda(scenario.steps, done);
})
})
})
In order to support multiple backgrounds, I'd have the option of passing an array or a finder object whose responsibility is to look for backgrounds based on some internal algorithm (e.g. directory and filename pattern matching).
Would this fit your needs?
This sounds like something that would fit.
And without having too much knowledge (yet?) of the inner workings, I can imagine that in a second iteration (after your version is operational) some of the background-tagged scenarios can even be included in the feature file itself: on parsing the feature file the tagged scenario is provided to the background parser that adds it to its library, so it can be reused by the feature parser on the following scenarios.
The ability to have multiple background is interesting. Here's what I would have like syntax. Negotiable.
Feature: X
# no background tag (in scenario => ``given background@`` ( or ``given background`` ))
# no background tag to support others projects
Background:
Given a fake zookeeper instance
With value "X" at "/some/location"
@generic (in scenario => ``given background@generic``)
Background:
Given a fake zookeeper instance
With value "Y" at "/some/generic"
@extendback (in scenario => ``given background@extendback``)
Background:
# import another background in background
Given background@generic
With value "Z" at "/some/other/extendback"
Scenario: A
Given background@
And a client doing ....
# X set
...
Scenario: B
Given background@generic
# Y set
....
Scenario: C
Given background@
Given background@extendback
# X, Y, Z sets
...
cordially Ami44
A few things I've been pondering over...
hospital-admissions.feature
# Defines a background (like a scenario except that it isn't executed)
Define: Middleton Hospital
Given a hospital called Middleton
with a 20 bed, male, cardiovascular ward called Summersham
and a 15 bed, female, respiratory ward called Bucklesham
Feature: Hospital Admissions
# Included for all scenarios in this feature
Background:
Middleton Hospital
Scenario: Admit a patient
Given a cardiovascular patient, Mr. Bob Hollness requires admission
When Mr. Hollness is admitted to bed 1 on Summersham ward
Then the bed becomes occupied
Scenario: Attempt to admit a patient into a full ward
Given a cardiovascular patient, Mr. Bob Hollness requires admission
but Bucklesham ward is full
Mr. Hollness cannot be admitted into Summersham ward
Scenario: Suggest alternative ward
# Included for just this scenario
Background:
Attempt to admit a patient into a full ward
When the Admissions clerk requests an alternative ward
Then they are offered bed 2 on Summersham ward
Scenario: Admit a patient into an alternative ward
# Implicitly includes 'Attempt to admit a patient into a full ward'
Background:
Suggest alternative ward
When Mr. Hollness is admitted to bed 2 on Bucklesham ward
Then the bed becomes occupied
However he is flagged as off template
patient-history.feature
Feature: Patient History
# No need to specify where this background was defined - all background / scenario titles must be unique
Background:
Middleton Hospital
Scenario: Audit patient
# Multiple backgrounds
Background:
Admit a patient
Move patient
Discharge patient
When an auditor reviews the patient history
They can see that he was admitted
And that he was moved
And that he was discharged
Still just food for thought
Define
Scenario: Suggest alternative ward
Background: Attempt to admit a patient into a full ward
Background: Another unique background
Given a cardiovascular patient, Mr. Bob Hollness requires admission
...
Ami44
I'm not keen on duplicating the word Background and the indentation would be optional. However I prefer your syntax for single background includes, e.g.
Scenario: Single Background
Background: Attempt to admit a patient into a full ward
Given a cardiovascular patient, Mr. Bob Hollness requires admission
Scenario: Multiple Background
Background:
Attempt to admit a patient into a full ward
Another unique background
Given a cardiovascular patient, Mr. Bob Hollness requires admission
Something else which I thought might make the specification more visually appealing is the inclusion of an optional Steps token
Scenario: Multiple Background
Background:
Attempt to admit a patient into a full ward
Another unique background
Steps:
Given a cardiovascular patient, Mr. Bob Hollness requires admission
Backgrounds have almost ready. These will be implemented as per Cucumber and https://github.com/acuminous/yadda/pull/60
Re-usable scenarios are somewhat harder. In issue #70 simoami suggested following jBehave's syntax
# A precondition to entire story
GivenFeature: path/to/precondition1.feature
Scenario: A scenario in which the user can run additional features as pre-requisites
# preconditions to scenario
GivenFeature: path/to/precondition2.feature,
Given ... // normal scenario steps
There are two problems with this...
So instead of including a path in the feature, I think we need a way to reference a scenario. I've been thinking of something like...
Scenario: Some reuseable scenario
Given A
When B
Scenario: A scenario in which the user can run other scenarios
[ Some reusable scenario ]
When I do something
[ Some reusable scenario ]
The above solution implies that the FeatureParser will have to know about all feature files, without necessarily running them.
Thoughts?
Hi Stephen, Sorry I just saw this.
The syntax to be more natural.
Not sure I understand this point.
path/to/precondition.feature implies Yadda is always run in node, but it can also be run from a browser.
Not sure what limitations you're referring to. The specified path is typically relative so it's possible to resolve it. Otherwise having a base path to the entire test suite, would help as well. Browsers as you know have the ability to load and process files asynchronously.
Also, by [ Some reusable scenario ] do you mean something like:
GivenScenario "some description identifying a given scenario"
I think it only presents half the value to reference external scenarios. And because scenarios live inside feature files it would be hard to identify the feature files that contain them. Our QA team is literally asking for a way to incorporate external tests from other modules as prerequisites. We run a mutli-product SaaS application where modules have dependencies and effects on other modules. So we need to have cross-module checks.
The GivenFeature is relevant and is being measured in this feature comparison: http://mkolisnyk.blogspot.com/2013/03/jbehave-vs-cucumber-jvm-comparison.html
See section "Input Data Sources"
Hi Simo,
The syntax to be more natural.
Sorry, I didn't explain myself very well. I would prefer not to include a relative path to another feature file within the specification. Instead I would prefer to refer to an included scenario as a user would do verbally, in a play script or legal document
Not sure what limitations you're referring to. The specified path is typically relative so it's possible to resolve it.
Agreed. I was being thick.
Also, by [ Some reusable scenario ] do you mean something like:
GivenScenario "some description identifying a given scenario"
Not quite, I literally mean
[ some description identifying a given scenario ]
It's quite common to use [ ] brackets in legal documents to refer to other sections. I'm not sure if there's an equivalent syntax in play scripts (e.g. for events which happen off stage or directions to the actors)
I think it only presents half the value to reference external scenarios.
Which half is it missing?
And because scenarios live inside feature files it would be hard to identify the feature files that contain them.
I think you would need to scan the fs or provide a feature file index for browser.
Our QA team is literally asking for a way to incorporate external tests from other modules as prerequisites.
An alternative which might meet your needs and stay consistent with Yadda's philosophy might be to allow the feature parser to respond to annotations, similar to how compiler directives work, e..g
# A precondition to entire story
@Run: path/to/precondition1.feature
Feature: some feature
@Run: path/to/precondition2.feature
Scenario: A scenario in which the user can run additional features as pre-requisites
Given ... // normal scenario steps
You would have to initialise the FeatureParser with the callbacks, e.g.
jsnew FeatureParser({ annotationHandlers: { run: loadPrecondition })
The GivenFeature is relevant and is being measured in this feature comparison
I agree this feature is important, but I don't want to rush it. Getting it wrong will cause a backwards compatibility headache. A temporary alternative might be to write your own FeatureParser. They are easy to plugin to the mocha parser if that's what you're using.
Out of curiosity, are you still working on this? I really really want to use this in my project already. Otherwise I have to change from framework maybe, and that would be a shame because i love it.
What I am looking for
Scenario: Just a scenario with reusable scenario's
Given I opened the app
I first want to run scenario X
And I want to do something I want
Then I want to run scenario Y also
And maybe even another step
Unfortunately I'm not getting much time for Yadda at the moment. I'm still fixing bugs and responding to questions. If there's a quick improvement I'll consider it too, but anything significant is on hold.
The real problem is that this and some of the other feature request aren't easy with the current architecture. Rather than twist the code base in knots I'm working on a rewrite, which will hopefully make improvements like this much easier.
For setting up a common structure. Cucumber uses a Background that is run at the start of each scenario.
Would like to see named backgrounds, that I can specify in a scenario: Given background A, and perhaps also backgrounds referring another background (circular references may throw errors).