JBehave
  1. JBehave
  2. JBEHAVE-646

@Named not respecting parameter order

    Details

    • Type: Bug Bug
    • Status: Resolved Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 3.6
    • Component/s: None
    • Labels:
      None
    • Number of attachments :
      0

      Description

      @Named doesn't seem to do its job, and parameter ordering in the method declaration seems to confuse the assignment code. For instance:

      "Given a $var1 with $var2 and $var3"

      void testVars(@Named("var3") String var3, @Named("var1") String var1, @Named("var2") String var2)

      When executing testVars, it assigns var3=$var3, var1=$var1, but var2=$var3

      Clearly, the correct assignment is var2=$var2

        Activity

        Hide
        Mauro Talevi added a comment -

        The @Named annotation is intended for use with parameterised scenarios (http://jbehave.org/reference/stable/parametrised-scenarios.html).

        Hence, you cannot use it in conjunction with the normal parameter matching, which uses natural ordering.

        Have a look at the trader example module for uses of the @Named annotation.

        Show
        Mauro Talevi added a comment - The @Named annotation is intended for use with parameterised scenarios ( http://jbehave.org/reference/stable/parametrised-scenarios.html ). Hence, you cannot use it in conjunction with the normal parameter matching, which uses natural ordering. Have a look at the trader example module for uses of the @Named annotation.
        Hide
        Diego Rivera added a comment -

        Understood - I guess this was a simple case of RTFM

        However, would this behavior be desirable? I.e. using "named" to supersede/supplant the ordering? It seems natural that if one chooses for parameters to be named, and uses @Named() to enforce it, that JBehave would respect that even in a non-parameterized scenario.

        Show
        Diego Rivera added a comment - Understood - I guess this was a simple case of RTFM However, would this behavior be desirable? I.e. using "named" to supersede/supplant the ordering? It seems natural that if one chooses for parameters to be named, and uses @Named() to enforce it, that JBehave would respect that even in a non-parameterized scenario.
        Hide
        Mauro Talevi added a comment -

        It actually turns out to be already possible - there was a unit test verifying this behaviour:

        StepCandidateBehaviour.shouldMatchMethodParametersByAnnotatedNamesInverseOrder.

        I create an example story out of it in trader example: named_parameters.story

        Have a look and let us know if this examples satisfies your requirement. If not, feel free to modify it and send us a patch demostrating what it should be doing.

        Show
        Mauro Talevi added a comment - It actually turns out to be already possible - there was a unit test verifying this behaviour: StepCandidateBehaviour.shouldMatchMethodParametersByAnnotatedNamesInverseOrder. I create an example story out of it in trader example: named_parameters.story Have a look and let us know if this examples satisfies your requirement. If not, feel free to modify it and send us a patch demostrating what it should be doing.
        Hide
        Arjan van Bentem added a comment -

        If the following is true:

        Hence, you cannot use it in conjunction with the normal parameter matching, which uses natural ordering.

        ...then isn't the documentation at http://jbehave.org/reference/stable/parameter-injection.html wrong? It states:

        One reason to use named parameters is that then we can have method parameter appearing in any order:

        @Given("a stock of symbol $symbol and a threshold of $threshold")
        public void aStock(@Named("threshold") double aThreshold, @Named("symbol") String aSymbol) {
            // ...
        }
        

        I'm seeing the same issue when using slightly complicated regexs, such as a regex in which the parameters are not surrounded with whitespace.

        For example, no issues, even though not all parameters are surrounded by whitespace:

        // Ordered parameters, with whitespace
        @Given("I have $a and $b")
        public void givenAAndB(String myA, String myB) {
            LOG.info("given A={}, B={}", myA, myB);
            assertThat(myA).isEqualTo("1st");
            assertThat(myB).isEqualTo("2nd");
        }
        
        // Named parameters, in natural order, WITHOUT whitespace after $a
        @When("doing $a, and $b")
        public void whenAAndB(@Named("a") String myA, @Named("b") String myB) {
            LOG.info("when A={}, B={}", myA, myB);
            assertThat(myA).isEqualTo("this");
            assertThat(myB).isEqualTo("that");
        }
        
        // Named parameters, reversed order, with whitespace
        @Then("we have $a or $b")
        public void thenAOrdB(@Named("b") String myB, @Named("a") String myA) {
            LOG.info("then A={}, B={}", myA, myB);
            assertThat(myA).isEqualTo("success");
            assertThat(myB).isEqualTo("failure");
        }
        

        ...but, troublesome when named parameters are not in the natural order, and not all parameters are fully surrounded with whitespace:

        // Named parameters, reversed order, WITHOUT whitespace after $a
        @Then("we have $a, $b")
        // Same with comma and quotes: @Then("we have '$a', '$b'")
        // Same without comma, with quotes: @Then("we have '$a' '$b'")
        // No problem for: @Then("we have $a for you, $b")
        public void thenACommaB(@Named("b") String myB, @Named("a") String myA) {
            // Will fail; parameters have been assigned in their natural order
            assertThat(myA).isEqualTo("a problem");
            assertThat(myB).isEqualTo("Houston");
        }

        ...with

        Given I have 1st and 2nd
        When doing this, and that
        Then we have success or failure
        And we have a problem, Houston
        

        ...I get:

        Failed to run story login.story
        org.junit.ComparisonFailure: expected:<'[a problem]'> but was:<'[Houston]'>
        

        So it seems that parameters always need to be surrounded by whitespace?

        (It's not so much an issue that a test would fail with PENDING, but silently falling back to the natural order doesn't seem to nice to me.)

        Show
        Arjan van Bentem added a comment - If the following is true: Hence, you cannot use it in conjunction with the normal parameter matching, which uses natural ordering. ...then isn't the documentation at http://jbehave.org/reference/stable/parameter-injection.html wrong? It states: One reason to use named parameters is that then we can have method parameter appearing in any order: @Given( "a stock of symbol $symbol and a threshold of $threshold" ) public void aStock(@Named( "threshold" ) double aThreshold, @Named( "symbol" ) String aSymbol) { // ... } I'm seeing the same issue when using slightly complicated regexs, such as a regex in which the parameters are not surrounded with whitespace. For example, no issues, even though not all parameters are surrounded by whitespace: // Ordered parameters, with whitespace @Given( "I have $a and $b" ) public void givenAAndB( String myA, String myB) { LOG.info( "given A={}, B={}" , myA, myB); assertThat(myA).isEqualTo( "1st" ); assertThat(myB).isEqualTo( "2nd" ); } // Named parameters, in natural order, WITHOUT whitespace after $a @When( "doing $a, and $b" ) public void whenAAndB(@Named( "a" ) String myA, @Named( "b" ) String myB) { LOG.info( "when A={}, B={}" , myA, myB); assertThat(myA).isEqualTo( " this " ); assertThat(myB).isEqualTo( "that" ); } // Named parameters, reversed order, with whitespace @Then( "we have $a or $b" ) public void thenAOrdB(@Named( "b" ) String myB, @Named( "a" ) String myA) { LOG.info( "then A={}, B={}" , myA, myB); assertThat(myA).isEqualTo( "success" ); assertThat(myB).isEqualTo( "failure" ); } ...but, troublesome when named parameters are not in the natural order, and not all parameters are fully surrounded with whitespace: // Named parameters, reversed order, WITHOUT whitespace after $a @Then( "we have $a, $b" ) // Same with comma and quotes: @Then( "we have '$a', '$b'" ) // Same without comma, with quotes: @Then( "we have '$a' '$b'" ) // No problem for : @Then( "we have $a for you, $b" ) public void thenACommaB(@Named( "b" ) String myB, @Named( "a" ) String myA) { // Will fail; parameters have been assigned in their natural order assertThat(myA).isEqualTo( "a problem" ); assertThat(myB).isEqualTo( "Houston" ); } ...with Given I have 1st and 2nd When doing this , and that Then we have success or failure And we have a problem, Houston ...I get: Failed to run story login.story org.junit.ComparisonFailure: expected:<'[a problem]'> but was:<'[Houston]'> So it seems that parameters always need to be surrounded by whitespace? (It's not so much an issue that a test would fail with PENDING, but silently falling back to the natural order doesn't seem to nice to me.)
        Hide
        Mauro Talevi added a comment -

        Hi,

        I've tried adding quotes and commas to
        StepCandidateBehaviour.shouldMatchMethodParametersByAnnotatedNamesInverseOrder but could not reproduce the behaviour you're finding.

        Could you please try to reproduce it in the StepCandidateBehaviour or provide a patch with either the unit test or an story that reproduces it?

        Show
        Mauro Talevi added a comment - Hi, I've tried adding quotes and commas to StepCandidateBehaviour.shouldMatchMethodParametersByAnnotatedNamesInverseOrder but could not reproduce the behaviour you're finding. Could you please try to reproduce it in the StepCandidateBehaviour or provide a patch with either the unit test or an story that reproduces it?
        Hide
        Arjan van Bentem added a comment -

        Hi Mauro,

        when using

        "I live on the $ith, but some call it the $nth";
        

        along with

        "When I live on the first, but some call it the ground"
        

        then things fail in 3.5.4.

        So:

        @Test
        public void shouldMatchMethodParametersByAnnotatedNamesInverseOrderWithLessWhitespace() throws Exception {
            AnnotationNamedParameterSteps steps = new AnnotationNamedParameterSteps();
            String patternAsString = "I live on the $ith, but some call it the $nth";
            Method method = stepMethodFor("methodWithNamedParametersInInverseOrder", AnnotationNamedParameterSteps.class);
            StepCandidate candidate = candidateWith(patternAsString, WHEN, method, steps);
            candidate.createMatchedStep("When I live on the first, but some call it the ground", namedParameters)
                    .perform(null);
            // Will fail:
            // java.lang.AssertionError: Expected: "first" got: "ground"
            assertThat(steps.ith, equalTo("first"));
            assertThat(steps.nth, equalTo("ground"));
        }
        

        As an aside: I'm seeing a related problem in /Old_JBehave_Issues/748 where @Named parameters in their natural order in some situations get a value from an Examples table (if used in the same scenario), but only if not fully surrounded with whitespace.

        Show
        Arjan van Bentem added a comment - Hi Mauro, when using "I live on the $ith, but some call it the $nth" ; along with "When I live on the first, but some call it the ground" then things fail in 3.5.4. So: @Test public void shouldMatchMethodParametersByAnnotatedNamesInverseOrderWithLessWhitespace() throws Exception { AnnotationNamedParameterSteps steps = new AnnotationNamedParameterSteps(); String patternAsString = "I live on the $ith, but some call it the $nth" ; Method method = stepMethodFor( "methodWithNamedParametersInInverseOrder" , AnnotationNamedParameterSteps.class); StepCandidate candidate = candidateWith(patternAsString, WHEN, method, steps); candidate.createMatchedStep( "When I live on the first, but some call it the ground" , namedParameters) .perform( null ); // Will fail: // java.lang.AssertionError: Expected: "first" got: "ground" assertThat(steps.ith, equalTo( "first" )); assertThat(steps.nth, equalTo( "ground" )); } As an aside: I'm seeing a related problem in /Old_JBehave_Issues/748 where @Named parameters in their natural order in some situations get a value from an Examples table (if used in the same scenario), but only if not fully surrounded with whitespace.
        Hide
        Arjan van Bentem added a comment -

        I noticed that http://jbehave.org/reference/stable/parameter-converters.html explains that the comma could be used for automatic conversion into a List:

        Given a stock of symbols STK1,STK2 and thresholds of 10.0,20.0
        

        However, that would not explain why quotes have the same erroneous result. Also, every other non-word character I tried has the same effect, so I doubt it's related to automatic conversion.

        Show
        Arjan van Bentem added a comment - I noticed that http://jbehave.org/reference/stable/parameter-converters.html explains that the comma could be used for automatic conversion into a List: Given a stock of symbols STK1,STK2 and thresholds of 10.0,20.0 However, that would not explain why quotes have the same erroneous result. Also, every other non-word character I tried has the same effect, so I doubt it's related to automatic conversion.
        Hide
        Mauro Talevi added a comment -

        The commas have nothing to do with it.

        Have you tried the latest snapshot? As I said above, I cannot reproduce your issue with it.

        Show
        Mauro Talevi added a comment - The commas have nothing to do with it. Have you tried the latest snapshot? As I said above, I cannot reproduce your issue with it.
        Hide
        Arjan van Bentem added a comment -

        Nope, I tried against 3.5.4, no the snapshot, but will do.

        Some more:

        org.jbehave.core.parsers.RegexPrefixCapturingPatternParser#findParametersToReplace finds ith, (including the comma) and nth as the parameter names. There the comma (or any non-word character, non whitespace in other tests) seems to be excessive to me.

        Show
        Arjan van Bentem added a comment - Nope, I tried against 3.5.4, no the snapshot, but will do. Some more: org.jbehave.core.parsers.RegexPrefixCapturingPatternParser#findParametersToReplace finds ith, (including the comma) and nth as the parameter names. There the comma (or any non-word character, non whitespace in other tests) seems to be excessive to me.
        Hide
        Arjan van Bentem added a comment -

        The above test works fine in 3.6-SNAPSHOT. Nice!

        (org.jbehave.core.parsers.RegexPrefixCapturingPatternParser.Parameter has changed, I guess that fixed it. As an aside: things for /Old_JBehave_Issues/748 have changed too, and are no longer dependent on any whitespace either. That made things slightly worse for that issue, but that's another matter. Thanks, @Mauro.)

        Show
        Arjan van Bentem added a comment - The above test works fine in 3.6-SNAPSHOT. Nice! ( org.jbehave.core.parsers.RegexPrefixCapturingPatternParser.Parameter has changed, I guess that fixed it. As an aside: things for /Old_JBehave_Issues/748 have changed too, and are no longer dependent on any whitespace either. That made things slightly worse for that issue, but that's another matter. Thanks, @Mauro.)
        Mauro Talevi made changes -
        Field Original Value New Value
        Status Open [ 1 ] Resolved [ 5 ]
        Fix Version/s 3.6 [ 17721 ]
        Resolution Fixed [ 1 ]

          People

          • Assignee:
            Unassigned
            Reporter:
            Diego Rivera
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: