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

Scenario should provide access to a "World" #1713

Closed
laeubi opened this issue Jul 29, 2019 · 16 comments
Closed

Scenario should provide access to a "World" #1713

laeubi opened this issue Jul 29, 2019 · 16 comments

Comments

@laeubi
Copy link

laeubi commented Jul 29, 2019

Currently it is possible to hook into and get the Scenario.
It would be good if the scenario would allow to access the "World" like in js/ruby in the following way:

Provide access to the glue code instances created by cucumber

         /**
	 * Gets the current instance of the glue code in this scenario
	 * @param clazz glue code type
	 * @return returns the glue instance of the the given class or <code>null</code> if not defined in this scenario
	 */
	<T> T getGlue(Class<T> clazz); 

This would allow to communicate between glue-code steps without the need of any additional framework like picocontainer/spring.

@mpkorstanje
Copy link
Contributor

Pico container already solves the problem of sharing state quite elegantly. What do we gain but a significant amount of complexity by implementing another way to do this?

@laeubi
Copy link
Author

laeubi commented Jul 29, 2019

The complexity is quite low since cucumber already knows all the class instances. The gain would be that it is possible to write Step code that does not need a specific framework (picocontainer for example) to work. For example it is not possible to use spring and picocontainer together you need to decide what to use.
A plain standard cucumber option without extension frameworks is easy to implement and works for many use-case scenarios.

@mpkorstanje
Copy link
Contributor

it is not possible to use spring and picocontainer together

Your suggestion doesn't solve this problem?

is easy to implement

Do you have examples of how PicoContainer (I think we recommend it as the default) isn't easy to implement/use?

@laeubi
Copy link
Author

laeubi commented Jul 29, 2019

For example: I wan't to provide a cucumber bridge for a product of mine (e.g. provide steps to help test stuff that can be archived with that) and I don't want to force the user to use picocontainer or spring in advance, second of that my product contains several modules that play together so I don't want to provide a big file that contains all steps... I can't do this with plain cucumber, because it does hold the created gluecode instance private and I have no way (beside some dirty reflection tricks calling private methods and field probably) to interact.

With that change, I simply can access the Scenario inside Hooks... Maybe we drop the Map stuff but at least the Glucode instance should be accessible....

@mpkorstanje
Copy link
Contributor

Have you considered implementing a custom backend?

I don't think it is feasible on the current master but on the develop-v5 branch backends are loaded via the SPI. Once loaded they'll be asked to registere any steps, hooks and other glue. They'll also be provided with a Container and Lookup. The container can be used to add classes to the DI context. The lookup can be used to access the DI context.

Because any execution of your steps will go through your implementation of StepDefinition.execute you can inject the Lookup as a custom parameter to all your steps should they need it.

I realize this is a bit more cumbersome then your proposed solution but it has the advantage of not exposing framework hooks to end users.

@laeubi
Copy link
Author

laeubi commented Jul 30, 2019

has the advantage of not exposing framework hooks to end users

As I (as a end user) must provide the glue, why should I'm not be able to access it? I can only describe my use-case, but what I heard from other customers some are also not convinced to pull in other frameworks (e.g. picocontainer or spring) because the want to write glue-libs for different department, and each department might use its own framework.
So if a Backend could get access to the Glues, it should be possible to hand it over to the scenario as well.
And since you must know the concrete class of the Glue I don't see any problem that there is any interference between glue codes.

@mpkorstanje
Copy link
Contributor

Fundamentally what are you trying to achieve by writing glue libraries?

@mpkorstanje
Copy link
Contributor

The reason I'm asking is because you're not the first person to come up with the idea of providing glue libs. Cucumber Ruby provided a web-steps lib for a while. Eventually it was removed because it made for boring and brittle scenarios. You can read about more about in Aslaks article The training wheels came off.

Rather then providing steps as a library you should consider providing your API as a library and let end users glue the different clients together in their step definitions.

@mpkorstanje
Copy link
Contributor

#1711 (comment)

Especially you want to support the "Specification Guys" so the don't need to know what steps are there but can find a list on there hand, automatically generated from projects code.

And based on your earlier comment I think you might be misunderstanding what the purpose of Cucumber is. Cucumber is a collaboration tool, not an automated testing tool. Having multiple departments each providing step libraries that specification guys puzzle together would be the opposite of what Cucumber is intended to do.

https://cucumber.io/blog/the-worlds-most-misunderstood-collaboration-tool/

@laeubi
Copy link
Author

laeubi commented Nov 3, 2019

Rather then providing steps as a library you should consider providing your AP
I as a library and let end users glue the different clients together in their step definitions.

We have different products using UIs, we don'T want each project to write there step definitions again and again. So why does this is "wrong" to try to reuse (glue-)code? Of course each project also contains dedicated glue codes but if you step away from very simple examples you would always need interaction between modules.

Beside that, this is a plain technical issue, if it is "wrong" why do rubby or other backends provide access to "the world" context? Are all thes cucumber-backends wrong and have to be fixed?

@laeubi laeubi reopened this Nov 3, 2019
@mpkorstanje
Copy link
Contributor

mpkorstanje commented Nov 3, 2019

Cucumber-JVM's dependency injection is a generalization of the World object in Ruby. Rather then injecting a single object, we can inject any object. You can also use a World object in Cucumber-JVM. It is a bit more tedious because unlike Ruby and Javascript we can't invoke a method against an arbitrary context.

public class StepDefinitions {

    private World world;

    public StepDefinitions(World world) {
        this.world = world;
    }

    @Given("some step")
    public void someStep() {
        world.service.doSomething();
        world.variable = "done something";
    }
}

class World {
    final MyService service = new MyService();
    String variable;
}

We have different products using UIs, we don'T want each project to write there step definitions again and again. So why does this is "wrong" to try to reuse (glue-)code?

You're not the first person to come up with the idea of providing glue libs. Cucumber Ruby provided a web-steps lib for a while. Eventually it was removed because it made for boring and brittle scenarios. You can read about more about in Aslaks article The training wheels came off.

@laeubi
Copy link
Author

laeubi commented Nov 3, 2019

Cucumber-JVM's dependency injection is a generalization of the World object in Ruby. Rather then injecting a single object, we can inject any object. You can also use a World object in Cucumber-JVM.

Was this added in Cucumber-jvm-5? AFAIK previously to make this work you either need to use Spring or PicoContainer, but not plain Cucumber

You're not the first person to come up with the idea of providing glue libs. Cucumber Ruby provided a web-steps lib for a while. Eventually it was removed because it made for boring and brittle scenarios. You can read about more about in Aslaks article The training wheels came off.

I already read this before, but I still can't tell the company 'Aslaks thinks you are wrong' ... :-\

@mpkorstanje
Copy link
Contributor

mpkorstanje commented Nov 3, 2019

Was this added in Cucumber-jvm-5? AFAIK previously to make this work you either need to use Spring or PicoContainer, but not plain Cucumber

No, you will still need a DI container for that. It was intended to illustrate the generalization.

I already read this before, but I still can't tell the company 'Aslaks thinks you are wrong' ... :-\

If you can't tell a company that the guy who makes the tool thinks the way the company wants to use the tool is wrong, then I don't know who can help you. 😆

If you need professional help setting people straight checkout the options here: https://cucumber.io/training and here https://cucumber.io/support

@mpkorstanje
Copy link
Contributor

We don't want each project to write there step definitions again and again.

Perhaps worth to address this explicitly. It seems to drive this entire feature request.

Generally if you use Cucumber to describe the behaviour of the system rather then to automate your test scripts you'll find that there are very few step definitions that get reused between features. Hence the recommendation to provide an API to your system as a library and let users glue different API operations together in their step definitions.

So while there will always be a few step definitions that will be duplicated across projects the cost of this duplication should be quite trivial compared to the cost of making them reusable. Esp since the underlying APIs are already reusable.

And since your situation seems to be quite unique, I don't see any reason to place the burden of that complexity within Cucumber JVM. Ultimately your organizations complexity is a burden for your organization to bear.

@laeubi
Copy link
Author

laeubi commented Nov 3, 2019

The point is: Different users use Cucumber differently, there can't be the one and only way. Nerveless, either someone think it is "wrong" or "right" does has nothing to do with technical implementation details.

On a technical level, there was a demand to access the Glue-Code instantiated by cucumber in a generic, standard cucumber way regardless of the used DI framework, that all this feature request is about, as Ruby/JS call it "World" and even the Cucumber-Java documentation do so, I probably have choose the wrong wording or make you think I want to generally change things how Cucumber works.

Then you asked about the Use-Case, and it turns into a discussion if we should use Cucumber at all or use it other ways round or if it is even worth to reuse step definitions (even if API would be 1:1 reusable we still need to define the same regexp/cucumber expression string over and over again).

As the Code calling the Before/After steps obviously knows the Glue-Classes (otherwise it can't call them) it seems to be an easy change to make this available via a public API (here the Scenario was suggested as it is already injectable but maybe another place suits more) and would improve the usefulness of Before/After steps with minimal effort. And as other backends already offers such things I don't see why cucumber-jvm should NOT provide such a way by default.

@mpkorstanje
Copy link
Contributor

Cucumber is a framework to support BDD. Every feature added to the framework adds comes at a cost. A cost in terms of complexity, maintenance, documentation, usage, ect. This cost must be weighed against the benefit of the feature.

The feature you suggested is both highly technical, of use to exactly one user, and supports a use case that has been found to be detrimental to writing behaviour focused Gherkin. As such I see no benefit to adding it to Cucumber JVM. I've heard no new arguments since I closed this on Sep 22 so I'll leave it at that.

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

No branches or pull requests

2 participants