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

Use Gherkin v4 #1035

Merged
merged 31 commits into from May 25, 2017
Merged

Use Gherkin v4 #1035

merged 31 commits into from May 25, 2017

Conversation

brasmusson
Copy link
Contributor

@brasmusson brasmusson commented Aug 4, 2016

This PR updates Cucumber-JVM to use the Gherkin v4 parser and compiler.

Notes:

  • Since this change contains non-backward compatible changes, the version is updated to 2.0.0-SNAPSHOT.
  • Since Gherkin in v3/v4 has changed the group id from info.cukes to io.cucumber, the group id of Cucumber-JVM is also changed to io.cucumber.
  • The formatter interface is re-worked completely (it had to it was previously defined in Gherkin v2), and is not based on events that are fired from inside Cucumber-JVM and that the formatters can register listeners for.
  • Now when compiling features to pickles, and the to test cases, the step keyword is not available when running the test cases (basically the scenarios), there for the generated snippets always use the first step keyword of the language, and the keyword is not used when reporting the steps.
  • When using notifications schemas for other testing frameworks (for instance JUnit), Feature: <feature name> have often been used as "class name", now the feature file path is used instead (as the feature AST is not available after compiling the feature to pickles).
  • Previously the line filtering has been quite flexible, for instance if specifying the line of a step - then the scenario that the step is part of has been executed, or is specifying the line of an example table - then all scenarios from that table have been executed. Now the pickle only contain information of the line of the Scenario (or the line of the Scenario Outline and the example row that created the pickle), so that is the only line(s) that will execute the test case of the pickle.
  • The Pickle class in Gherkin does not have a getter for the tags of the pickle, therefore reflection has to be used to access the pickle tags.
  • The GherkinDialect class in Gherkin does not have a getter for each keyword, therefore reflections is used to implement the --i18n option.
  • To not lose the support to run Cucumber-JVM in OSGi containers, Gherkin need to define the Java jar as a bundle (chore(deps): update cucumber/action-publish-pypi action to v3 gherkin#221).

All in all, I do not see any blocker for merging this and creating a 2.0.0-SNAPSHOT. Before releasing a 2.0.0 version some more things (pretty and html formatters, OSGi support) are needed though.

@aslakhellesoy
Copy link
Contributor

You are a machine @brasmusson ! I'll do everything I can to cut a new release this week. Thanks for your awesome work.

@mattwynne
Copy link
Member

@aslakhellesoy are you the only person who can make releases? Is there anyone else with the experience / authority to merge this PR? Seems a shame for this to get stuck for so long just because you're busy.

Copy link
Contributor

@mpkorstanje mpkorstanje left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed up to 51c8656

  • Might be worth putting this on the backlog. Maven Relocation
  • Is there a reason not to match the package structure to the groupId? E.g. io.cucumber.api rather then cucumber.api?

Copy link
Contributor

@mpkorstanje mpkorstanje left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the [JUnit] changes

Would suggest moving contents of cucumber.runtime.junit into cucumber.api.junit so all classes aside from Cucumber can be package private.

PickleWrapper and PickleStepWrapper implement Serializable but their contents is not serializable (infact, their contents is not needed at all).

I don't quite understand SanityChecker. Should probably be in test sources.

Submitted nitpicks as #1122. No point in writing them out.


public ExecutionUnitRunner(Runtime runtime, CucumberScenario cucumberScenario, JUnitReporter jUnitReporter) throws InitializationError {
public ExecutionUnitRunner(Runner runner, PickleEvent pickleEvent, JUnitReporter jUnitReporter) throws InitializationError {
super(ExecutionUnitRunner.class);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can tell this should be super(null). There is no reason to scan this class for annotations.

ScenarioImpl scenarioResult = new ScenarioImpl(bus, pickleEvent.pickle);
for (TestStep step : testSteps) {
Result stepResult = step.run(bus, pickleEvent.pickle.getLanguage(), scenarioResult, skipNextStep);
if (stepResult.getStatus() != Result.PASSED) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess you intended this to be an enum comparison not a string?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also causing problems in TestNgReporter#result. It compares strings against objects for Result.UNDEFINED.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the Result class has moved to this project from gherkin, there is an opportunity improve things like the definition of status codes. I'll look into that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the introduction of an enum for the result statuses in #1133, this kind of problem should be eliminated.

@@ -57,10 +62,10 @@ public Cucumber(Class clazz) throws InitializationError, IOException {

ResourceLoader resourceLoader = new MultiLoader(classLoader);
runtime = createRuntime(resourceLoader, classLoader, runtimeOptions);

formatter = runtimeOptions.formatter(classLoader);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this. Is this needed? This also happens in Runner#buildBackendWorlds which calls runtimeOptions.getPlugins();

import java.util.HashMap;
import java.util.Map;

public class TestSourcesModel {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think TestSourcesModel is part of the public API but I can't tell for sure. Whole thing should probably be package private.

@@ -1,83 +1,99 @@
package cucumber.runtime.model;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This package has become quite anemic. All closely tied to RuntimeOptions. Might want to consolidate this, RuntimeOptions and friends into a options package.

import java.util.ArrayList;
import java.util.List;

public class DataTableDiff extends DataTable {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and other classes are all public but don't need to be. They're not part of the public API as far as I can see.

public boolean apply(PickleEvent pickleEvent) {
String picklePath = pickleEvent.uri;
if (!lineFilters.containsKey(picklePath)) {
return true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be false. If a Pickle isn't referenced in the rerun file it shouldn't be added to the list of pickles to execute.

Unit tests confirm the behavior is as intended, but I can't find any thing to explain this behavior there either.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I finally remembered why it should be true, see the (new) explaining comment in the test case

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. The runner presents each file[:line] arguments as having or semantics. But internally it first finds all feature files by looking at the file part and then reduces the set of tests with the line predicate.

@mpkorstanje
Copy link
Contributor

mpkorstanje commented May 17, 2017

Reviewed the [Core] changes

Took me a while to do this, this change is somewhat voluminous but I found nothing major. This is mostly a straightforward rewrite against a changed API. There are some TODOs present and a few disabled tests but they don't seem to matter too much.

Pushed more more nitpicks to #1122. No point in writing them out.

@brasmusson
Copy link
Contributor Author

@mpkorstanje Your effort is much appreciated.

@brasmusson
Copy link
Contributor Author

Is there a reason not to match the package structure to the groupId? E.g. io.cucumber.api rather then cucumber.api?

I do not know, when I got involved the groupId did correspond to the web site (http://cukes.info/), but the package structure was cucumber.<x>, gherkin.<x>. Now then the web site has moved to http://cucumber.io, the goupdId changes seems reasonable (and the newer gherkin release has changed groupId).

@mattwynne
Copy link
Member

mattwynne commented May 18, 2017

@mpkorstanje Your effort is much appreciated.

Amen! 👏


@Override
public void embedding(String mimeType, byte[] data) {
reporter.embedding(mimeType, data);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can not find where this method has been replaced with an event listener. From what I can see this is not needed as the Runtime takes care of this now and will inform the reporter from the pllugins. The TestNgReporter itself prints to sysout and doesn't care about embeddings.

So no problem.

@mpkorstanje
Copy link
Contributor

Reviewed the [TestNG] changes

Nothing major.

Pushed a fix for the string vs non-string comparison in the TestNgReporter to #1122.

Pushed more more nitpicks to #1122.

@aslakhellesoy aslakhellesoy merged commit fd1b645 into master May 25, 2017
aslakhellesoy added a commit that referenced this pull request May 25, 2017
@aslakhellesoy
Copy link
Contributor

Hey @brasmusson and @mpkorstanje - awesome work on this and sorry it took so long!

@brasmusson
Copy link
Contributor Author

@mpkorstanje

I don't quite understand SanityChecker. Should probably be in test sources.

Yes, it is test related, but it is also used in the test of picocontainer. AFAIK it needs to be in the src/main part to be usable from the picocontainer module (on the other hand all of that testing maybe should be moved to the junit module).

@lock
Copy link

lock bot commented Oct 25, 2018

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Oct 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants