JBehave
  1. JBehave
  2. JBEHAVE-261

New syntax for Given with many parameters

    Details

    • Type: Improvement Improvement
    • Status: Open Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: Core
    • Labels:
      None
    • Number of attachments :
      0

      Description

      A given step might look like :

      Given a person (first name) Bruno (last name) Bieth born 2010-01-01 in Tombouctou living in Canada driving 10,000 miles per year

      It can be hard to read. Passed a certain amount of parameters I suggest the following syntax :

      Given a person
          - First Name : Bruno
          - Last Name : Bieth
          - Birth date : 2010-01-01
          - Birth country : Tombouctou
          - Country of residency : Canada
          - Miles driven per year : 10,000
      

      The java code would look like :

      @GivenDetail( "a person" )
      public void aPerson(
      		@Named("First Name") String firstName, 
      		@Named("Last Name") String lastName, 
      		@Named("Birth date") DateTime birthDate,
      		@Named("Birth country") String birthCountry,
      		@Named("Country of residency") String countryOfResidency,
      		@Named("Miles driven per year") Integer milesPerYear
      ) {			
      	person = new Person(firstName,lastName,birthDate,birthCountry,countryOfResidency,milesPerYear);
      }
      

      The factory could use another CandidateSteps instance, say :

      public class DetailedSteps implements CandidateSteps {
      
      	private CandidateSteps delegate;
      	private StepsConfiguration configuration;
      	private Object instance;
      
      	public DetailedSteps(StepsConfiguration configuration, CandidateSteps delegate, Object instance) {
      		this.configuration = configuration;
      		this.delegate = delegate;
      		this.instance = instance;
      	}
      	
      	@Override
      	public CandidateStep[] getSteps() {
      		return getSteps( instance.getClass() );
      	}
      
      	@Override
      	public CandidateStep[] getSteps(Class<?> stepsClass) {
      		List<CandidateStep> steps = new ArrayList<CandidateStep>( Arrays.asList( delegate.getSteps(stepsClass)));
      				
      		for( Method method : stepsClass.getMethods() ) {
      			GivenDetail annotation = method.getAnnotation(GivenDetail.class);
      			if( annotation != null ) {
      				steps.add( createGivenDetail( method, annotation ) );
      			}
      		}
      		
      		return steps.toArray(new CandidateStep[steps.size()]);
      	}
      
      	private CandidateStep createGivenDetail(final Method method,
      			GivenDetail annotation) {
      		return new CandidateStep(annotation.value(), annotation.priority(), StepType.GIVEN, method, instance, new StepPatternBuilder() {			
      			@Override
      			public String[] extractGroupNames(String string) {
      				List<String> names = new ArrayList<String>();
      				for( Annotation[] annotations : method.getParameterAnnotations() ) {
      					for( Annotation annotation : annotations ) {
      						if( annotation instanceof Named ) {
      							names.add( ((Named)annotation).value() );
      						}
      					}
      				}
      				return names.toArray(new String[names.size()]);
      			}
      			
      			@Override
      			public Pattern buildPattern(String matchThis) {
      				String[] groups = extractGroupNames("");
      				String pattern = matchThis.replaceAll(" ", "\\\\s+" );
      				for( String group : groups ) {
      					pattern += "\\s+-\\s+" + group.replaceAll( " ", "\\\\s+" ) + "\\s*:\\s+(.*)";
      				}
      				return Pattern.compile( pattern );
      			}
      		},configuration.getParameterConverters(),configuration.getStartingWordsByType());
      	}
      
      	@Override
      	public List<Step> runAfterScenario() {
      		return delegate.runAfterScenario();
      	}
      
      	@Override
      	public List<Step> runAfterStory(boolean embeddedStory) {
      		return delegate.runAfterStory(embeddedStory);
      	}
      
      	@Override
      	public List<Step> runBeforeScenario() {
      		return delegate.runBeforeScenario();
      	}
      
      	@Override
      	public List<Step> runBeforeStory(boolean embeddedStory) {
      		return delegate.runBeforeStory(embeddedStory);
      	}
      
      }
      

        Activity

        Mauro Talevi made changes -
        Field Original Value New Value
        Fix Version/s 2.5.1 [ 16283 ]
        Hide
        Mauro Talevi added a comment -

        Have you considered using ExamplesTable? E.g.

        Given a person with details

        First Name Last Name Birth date ...
        Bruno Bierth 2010-01-01 ...

        The only thing it does no have at present is the auto-conversion of the parameter values to Java type.

        I would not think that should be too hard though.

        Show
        Mauro Talevi added a comment - Have you considered using ExamplesTable? E.g. Given a person with details First Name Last Name Birth date ... Bruno Bierth 2010-01-01 ... The only thing it does no have at present is the auto-conversion of the parameter values to Java type. I would not think that should be too hard though.
        Hide
        Bruno Bieth added a comment -

        Sort of. I reckon it looks good on the wiki but in a text file you might end up with this :

        Given a series:
        |name|management fee|incentive fee|net asset value|gross asset value|high water mark|close date|
        |Series 0110|2%|20%|$100|$100|$100|2010-01-01|
        

        Of course it's a matter of preference, but I like more that :

        Given a series
        	- Name : Series 0110
        	- Management Fee : 2%
        	- Incentive Fee : 20%
        	- Net Asset Value : $200
        	- Gross Asset Value : $200
        	- High Water Mark : $200
        	- Close date : 2010-01-01
        
        Show
        Bruno Bieth added a comment - Sort of. I reckon it looks good on the wiki but in a text file you might end up with this : Given a series: |name|management fee|incentive fee|net asset value|gross asset value|high water mark|close date| |Series 0110|2%|20%|$100|$100|$100|2010-01-01| Of course it's a matter of preference, but I like more that : Given a series - Name : Series 0110 - Management Fee : 2% - Incentive Fee : 20% - Net Asset Value : $200 - Gross Asset Value : $200 - High Water Mark : $200 - Close date : 2010-01-01
        Hide
        Mauro Talevi added a comment -

        There is also the question of parsing to consider: having a tabular structure for table-like input is
        much easier to parse. So we could have an ExamplesMap, similar in concept to ExamplesTable, but
        one that only maps key to values and could be expressed as text:

        Name Series 0110
        Management Fee 2%

        ....

        Close date 2010-01-01
        Show
        Mauro Talevi added a comment - There is also the question of parsing to consider: having a tabular structure for table-like input is much easier to parse. So we could have an ExamplesMap, similar in concept to ExamplesTable, but one that only maps key to values and could be expressed as text: Name Series 0110 Management Fee 2% .... Close date 2010-01-01
        Hide
        Bruno Bieth added a comment -

        Well I've been using the DetailedSteps class without problems so far.

        In the ParameterConverterStepsFactory (see JBEHAVE-258) instead of

        candidateSteps[i] = new Steps(configuration, stepsInstance);
        

        I do the following :

        candidateSteps[i] = new DetailedSteps( configuration, new Steps(configuration, stepsInstance), stepsInstance );
        
        Show
        Bruno Bieth added a comment - Well I've been using the DetailedSteps class without problems so far. In the ParameterConverterStepsFactory (see JBEHAVE-258 ) instead of candidateSteps[i] = new Steps(configuration, stepsInstance); I do the following : candidateSteps[i] = new DetailedSteps( configuration, new Steps(configuration, stepsInstance), stepsInstance );

          People

          • Assignee:
            Unassigned
            Reporter:
            Bruno Bieth

            Dates

            • Created:
              Updated: