Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java8 - Max number of arguments in a step definition #1554

Closed
petosorus opened this issue Feb 5, 2019 · 7 comments
Closed

Java8 - Max number of arguments in a step definition #1554

petosorus opened this issue Feb 5, 2019 · 7 comments
Labels
⚡ enhancement Request for new functionality

Comments

@petosorus
Copy link

Summary

Using Kotlin, I noticed a step definition cannot have more than 9 arguments. I have some fairly complicated steps that need 10 or more arguments and that I cannot strip anymore.

I looked into it and it is a Cucumber limitation, coming from the fact that it defines interfaces for 1 to 9 arguments but no more (in StepdefBody.java)

Expected Behavior

It would nice to have the possibility of using more than 9 arguments.

Current Behavior

No more than 9 arguments can be put in for a step.

Possible Solution

Would it be possible to rely not on hardcoded interfaces for 1 to 9 arguments but to something with a dynamic number of arguments?
I'm willing to propose a fix that way, just need to look into code more.

Otherwise, I could add more interfaces, but that's ugly and not really desirable.

Context & Motivation

I have a complicated step that needs either more than 9 arguments, an ugly hack of splitting one of the arguments to get more data out of this limitation, or a rethinking of the way we write feature tests which would not be as close as reality.

Your Environment

  • Version used: 4.2.2
@mlvandijk mlvandijk added ⚡ enhancement Request for new functionality Java 8 labels Feb 5, 2019
@mlvandijk
Copy link
Member

@petosorus To better understand your use case, could you provide a real world example of when you would want to use more than 10 / unlimited arguments?

@petosorus
Copy link
Author

Yeah, here you go

Then("^A job exists on scheduling simulation (\\d+) on resource (\\w+)/(\\w+)/(\\w+) for item (\\w+) of (\\d+)/(\\w+) from J(\\d+) - (\\w+) to J(\\d+) - (\\w+)$") {
	simulationId: Int, companyCode: String, establishmentCode: String, resourceCode: String,
	itemCode: String, quantity: Int, unitCode: String,
	startDay: Int,startTime: String, endDay: Int, endTime: String -> {
     // Stuff
} 

Basically we created jobs that are time dependant, and we want to check they exist at the right time on the right day of the week (the "J(\d+)" part).

Only unique thing on those would be an id as it's dynamic data do everything we have as an argument here is useful.

@mlvandijk
Copy link
Member

Some thoughts (that may or may not help you - feel free to ignore if you disagree): 1. This example contains a lot of detail. Personally, I would find this hard to read and immediately understand what your system does. If this scenario is about a job existing at a particular day, is the resource information really important? And if not, could you push that down to the step definition? 2. If the resource IS important to the scenario, and you need to check for different resources, could you create a set of "resource" objects with companyCode, establishmentCode, resourceCode based on a meaningful name for that resource? 3. If you really need all of the above, you could still put day & time into one string and parse that into a DateTime? which would save 2 parameters...

@petosorus
Copy link
Author

I agree we could be more concise, but my interrogation still stands.
Is there any reason why there is a hard limit on 9 arguments? If not, why was it done the way it is instead of having something like varargs?

@mlvandijk
Copy link
Member

Honestly, I wouldn't know. The only reason I could think of would be that adding unlimited arguments would be a bit of a smell.

@mpkorstanje
Copy link
Contributor

mpkorstanje commented Feb 5, 2019

There currently is no Kotlin backend so we are using the Java backend instead. In Java a lambda needs a backing functional interface. And for Java to be able to determine the type of each argument it also has to be a generic interface. So we generate the lambdas and interfaces using a nice bit of Groovy templating. The reason the limit is 9 has a rather practical cause. It's the largest single digit number. So without padding any zeros the class names still look good.

While its possible to increase the number of allowed parameter it would probably be better to implement a Kotlin backend that uses kotlin.Function. Unlike Java it should be possible to directly get the parameters from the lambda by using Function.reflect, thus no need to limit the number of parameters at all.

But I haven't tried this yet. Feel free to give it a shot!

@mpkorstanje
Copy link
Contributor

Continued in #1829

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
⚡ enhancement Request for new functionality
Projects
None yet
Development

No branches or pull requests

3 participants