JBehave

jBehave should be more intelligent/flexible with regards to prioritisation of steps

Details

  • Type: New Feature New Feature
  • Status: Resolved Resolved
  • Priority: Minor Minor
  • Resolution: Fixed
  • Affects Version/s: None
  • Fix Version/s: 3.0
  • Component/s: Core
  • Labels:
    None
  • Patch Submitted:
    Yes
  • Number of attachments :
    2

Description

BDD's strength relies on being able to write fluent scenarios. jBehave's support for this is very good, but there is still room for improvement. For example a typical scenario might read...

Scenario: Schedule Patient Discharge

Given a medical patient called Bob Holness who is not medically fit
When I change Bob's state to medically fit
And select a discharge time of tomorrow morning
And select a discharge complexity of 3
Then Bob's discharge schedule should be displayed on the ward board

Now in a related scenario let's say I want to cancel while rescheduling a discharge...

Scenario: Cancel Rescheduling Patient Discharge

Given a medical patient called Bob Holness who already has a discharge schedule
When I reiterate that Bob's state is medically fit
And select a discharge time of tomorrow morning
And cancel the discharge schedule
Then Bob's old discharge schedule should be displayed on the ward board

The underlying implementation of assserting Bob's actual discharge schedule is the same, but I want to emphasise the expression of intent through use of words such as old, new, still, etc.

jBehave partially supports this through aliases

MySteps.java
@Then('''$patient discharge schedule should be displayed on the ward board''')
@Aliases(values=['''$patient old discharge schedule should be displayed on the ward board'''])
public void assertDischargeScheduleOnWardPage(Patient patient) {
	wardBoardPage.assertDischargeSchedule(patient)
}

The trouble is that the above fails because of the way in which jBehave matches and prioritises steps. Both "Then" and "Alias" steps will match the sentence
"Bob's old discharge schedule should be displayed on the ward board", but "Then" will be prioritised based on it's declaration order, causing the value "Bob's old" to be passed to the PatientParameterConverter. Since no patient exists with the name "Bob's old", the parameter converter will return null and the test fails.

Currently the workaround is to reword the steps slightly to prevent both of them matching...

Then "Bob's" discharge schedule should be displayed on the ward board
Then "Bob's" old discharge schedule should be displayed on the ward board

or

Then Bob's discharge schedule should be displayed on the ward board
Then Bob's old discharge schedule should now be displayed on the ward board

but both are inferior to the original. A nicer (and fairly easy) solution would be to base this priortisation on similarity with the string step, using something like the Levenshtein distance. Harder, but better yet would be to make the prioritsation configurable.

I've attached the first solution (with lots of printlns so you can see how well the prioriisation works).

Activity

Hide
Paul Hammant added a comment -

Interesting. I've not looked at the patch. There is a prioritization scheme already (plain numeric attached to the annotation), but that's not why I'm commenting.

Thinking about the language of what you're doing, and concentrating on the Given lines only :-

Given a medical patient called Bob Holness who is not medically fit
vs
Given a medical patient called Bob Holness who already has a discharge schedule

What it "who" were a synonym for And here?
Such that, in terms of fitting the current JBehave, the Givens could be re-written as

Given a medical patient called Bob Holness
And is not medically fit
vs
Given a medical patient called Bob Holness
And already has a discharge schedule

Obviously that's more Inglish than English, but it could point to an enhancement where subtle 'And' breaks could be recognized at subjective or objective case pronouns*. Subject to configuration of course.

Of course, your issue is with the matching of the Then line, not the Given. Towards that, have you thought about :-

@Then("Then $Bob's $OldOrNot discharge schedule should be displayed on the ward board")

Arghh... those two vars are too close together, and I'm not sure we can get an apostrophe-s situation to be left out of the matching group. Ok, ignore me.

  • Paul
Show
Paul Hammant added a comment - Interesting. I've not looked at the patch. There is a prioritization scheme already (plain numeric attached to the annotation), but that's not why I'm commenting. Thinking about the language of what you're doing, and concentrating on the Given lines only :- Given a medical patient called Bob Holness who is not medically fit vs Given a medical patient called Bob Holness who already has a discharge schedule What it "who" were a synonym for And here? Such that, in terms of fitting the current JBehave, the Givens could be re-written as Given a medical patient called Bob Holness And is not medically fit vs Given a medical patient called Bob Holness And already has a discharge schedule Obviously that's more Inglish than English, but it could point to an enhancement where subtle 'And' breaks could be recognized at subjective or objective case pronouns*. Subject to configuration of course. Of course, your issue is with the matching of the Then line, not the Given. Towards that, have you thought about :- @Then("Then $Bob's $OldOrNot discharge schedule should be displayed on the ward board") Arghh... those two vars are too close together, and I'm not sure we can get an apostrophe-s situation to be left out of the matching group. Ok, ignore me.
  • Paul
Hide
Stephen Cresswell added a comment -

Hi Paul,

Using Who and And interchangeably on a per step cases would work well. The Given steps I used as examples are some of our more simplistic, there are lots more variations...

"a $gender, $speciality patient called $name, in "$location" who is $state
e.g. Given a male, cardiovascular patient called Bob Holness, in "Bed 05, Ward 1", who is not medically fit

Being able to split these up into smaller steps would make the scenarios more readable and reduce the number of complex steps....

Given a male patient called Bob Holness // we should probably auto assign gender based on known names
with a cardiovascular speciality
located in Bed 05, Ward 1
who is not medically fit

"but" would be a useful synonym too

Then Bob's bed changes to Bed 6
but his* admission date stays as 15/07/74

*our PatientParameterConverter is smart enough to recognise "his/her" and use the "current" patient from our test context instead of doing a db retrieval on first name

Show
Stephen Cresswell added a comment - Hi Paul, Using Who and And interchangeably on a per step cases would work well. The Given steps I used as examples are some of our more simplistic, there are lots more variations... "a $gender, $speciality patient called $name, in "$location" who is $state e.g. Given a male, cardiovascular patient called Bob Holness, in "Bed 05, Ward 1", who is not medically fit Being able to split these up into smaller steps would make the scenarios more readable and reduce the number of complex steps....
Given a male patient called Bob Holness // we should probably auto assign gender based on known names with a cardiovascular speciality located in Bed 05, Ward 1 who is not medically fit
"but" would be a useful synonym too
Then Bob's bed changes to Bed 6 but his* admission date stays as 15/07/74
*our PatientParameterConverter is smart enough to recognise "his/her" and use the "current" patient from our test context instead of doing a db retrieval on first name
Hide
Mauro Talevi added a comment -

Added injectable PrioritisingStrategy in StepFinder with default ByPriorityField impl.
Added alternative ByLevenshteinDistance impl.

Show
Mauro Talevi added a comment - Added injectable PrioritisingStrategy in StepFinder with default ByPriorityField impl. Added alternative ByLevenshteinDistance impl.

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: