layout | nav | date | title | author |
---|---|---|---|---|
post |
blog |
2018-05-19 02:00:00 -0700 |
Announcing Cucumber-JVM v3.0.0 |
mpkorstanje |
With great joy and some relief I'm happy to announce Cucumber-JVM 3.0.0!
Here follows a summary of notable changes, and the non backward compatible changes. The full change log is available here.
Cucumber expressions have been implemented! Cucumber Expressions were introduced nearly a year ago in Cucumber.rb and Cucumber.js. Introducing them to cucumber-jvm required a fairly involved redesign that prompted a rewrite of Data Tables. It was also one of the reasons that has motivated us to drop support for several the less used languages.
You can use Cucumber Expressions as described on the new docs site.
To add custom parameters you have to place an implementation of cucumber.api.TypeRegistryConfigurer
on the glue path.
Most importantly DataTable
has moved from cucumber.api.DataTable
to io.cucumber.datatable.DataTable
and its API has
changed significantly. You can use the custom data table types as
described in the project README.
To add custom data table types you have to place an implementation of cucumber.api.TypeRegistryConfigurer
on the glue path.
public class TypeRegistryConfiguration implements TypeRegistryConfigurer {
@Override
public Locale locale() {
return ENGLISH;
}
@Override
public void configureTypeRegistry(TypeRegistry typeRegistry) {
typeRegistry.defineDataTableType(new DataTableType(
Grocery.class,
(Map<String, String> row) -> new Grocery(
row.get("name"),
Price.fromString(row.get("price"))
)
));
}
}
This may look a bit tedious. But you can also use your favourite object mapper library instead.
ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper();
typeRegistry.defineDataTableType(new DataTableType(
Grocery.class,
(Map<String, String> row) -> objectMapper.convertValue(row, Grocery.class))
);
Cucumber 1.x and 2.x used a library called XStream as a central building block for both data tables and type conversion.
However the usage of XStream in combination with Cucumber was poorly documented and it did not allow for the use of other Object Mappers (e.g. Jackson) which made it impossible to reuse domain objects. As XStream is not compatible with Java 9 it was also problem in long term.
With the introduction of Cucumber Expressions half of the use case for XStream disappeared. It was not realistic to use both systems next to each other so now was a good time to remove it entirely.
As such XStream has been removed from Cucumber. This means that @Delimiter
, @Format
, @Transformer
,
@XStreamConverter
, @XStreamConverters
and any other annotations from XStream will no longer work. These must be
replaced by DataTableType
or ParameterType
.
We're not providing a migration guide in this blog post. If you have a specific question about how to migrate, please contact us and we'll update the documentation accordingly.
Adds hooks that are invoked before and after a step.
The hooks have 'invoke around' semantics. Meaning that if a before step hook is executed the after step hooks will also be executed regardless of the result of the step. If a step did not pass, the following step and its hooks will be skipped.
To support the invoke around semantics the TestStep event has been replaced with an interface. Its concrete implementation split into HookTestStep and PickleStepTestStep. All subclass specific methods in TestStep have been deprecated.
During a dry run all hooks will be reported as skipped. In prior implementations the before and after scenario hooks were unskippable and were simply not included in a dry run.
Cucumber JVM is developed by volunteers who are all donating part of their spare time. Currently the core team of Cucumber-JVM consists of 3-4 people. This makes it hard to keep up with current developments in Cucumber, such as upgrading Gherkin, adding Tag Expressions and Cucumber Expressions, while also evaluating issues and pull requests.
To be able to keep developing cucumber-jvm, we are looking to focus more on the languages and components that are used the most. We started looking at how Cucumber was used. We found that most people are using Java, combined with JUnit or TestNg as a test framework. About half our users don't use a DI container; the other half uses Picocontainer, Spring or Guice. For more details, see below.
We can also see that many languages aren't used much at all. Since the language modules are fairly complex and consume a large amount of time, we have decided to stop supporting them. By decreasing our overall workload, we will be able to focus more on those components that used the most. Unfortunately, this means that the Scala, Groovy, Clojure, Jython, JRuby, Rhino, and Gosu implementations of Cucumber are no longer supported.
While these implementations have been removed from the cucumber-jvm project, they are still available as part of the Cucumber project. If you are interested in maintaining any of these implementations, please contact us so we can set you up!
Cucumber-JVM comes in four parts:
-
The core is required for all projects that want to use cucumber-jvm
-
A backend. This can be Java, Groovy, Scala, ect.
-
A runner. Aside from the command line provided by core, people can use JUnit or TestNg.
-
A DI container such as Picocontainer, Spring, or Guice.
Each of these modules costs time and effort to maintain. So we gathered some date on which are actually used. Below are the statistics for info.cukes1 from September 2017. The number of downloads indicates how often the artifact was downloaded from maven central2.
cucumber-core was downloaded 202244 times in a single month.
|Artifact | Downloads | % of total |
|-----------------------|-----------:|--------------:|
|cucumber-java | 182103 | 92.31% |
|cucumber-scala_2.11 | 5297 | 2.69% |
|cucumber-groovy | 5005 | 2.54% |
|cucumber-clojure | 1091 | 0.55% |
|cucumber-scala_2.12 | 971 | 0.49% |
|cucumber-jython | 884 | 0.45% |
|cucumber-jruby | 827 | 0.42% |
|cucumber-rhino | 608 | 0.31% |
|cucumber-scala | 394 | 0.20% |
|cucumber-gosu | 83 | 0.04% |
|cucumber-scala_2.10 | 0 | 0.00% |
|-----------------------|------------|---------------|
|total | 197263 | 100.00% |
|cucumber-core | 202244 | 102.53% |
Looking at the numbers, there is a large gap between Java and the other JVM languages. There is also a large gap between the runners up (Groovy and Scala) and the rest of the pack. Missing from this table is cucumber-java8. This module depends on cucumber-java and its usage (with 35012 downloads) represents 19.22% of cucumber-java.
Oddly enough, the overall downloads total does not equal that of cucumber-core, suggesting there are one or more custom backend implementations (e.g. cukes in space).
|Artifact | Downloads | % of total |
|-----------------------|----------:|--------------:|
|cucumber-picocontainer | 63194 | 61.05% |
|cucumber-spring | 30112 | 29.09% |
|cucumber-guice | 8662 | 8.37% |
|cucumber-weld | 769 | 0.74% |
|cucumber-openejb | 568 | 0.55% |
|cucumber-needle | 144 | 0.14% |
|cucumber-osgi | 57 | 0.06% |
|-----------------------|-----------|---------------|
|total | 103506 | 100.00% |
|cucumber-core | 202244 | 195.39% |
Picocontainer, Spring and Guice are the most used DI containers. However, there is a huge discrepancy in downloads with core, which suggests that people either use a custom container or no DI container at all. We don't know why this is, although the lack of documentation might have something to do with it.
|Artifact | Downloads | % of total |
|-----------------------|-----------:|--------------:|
|cucumber-junit | 176769 | 83.00% |
|cucumber-testng | 35913 | 16.86% |
|cucumber-android | 291 | 0.14% |
|-----------------------|------------|---------------|
|total | 212973 | 100.00% |
|cucumber-core | 202244 | 94.96% |
Most people use JUnit, some use TestNg. Curiously enough, some people might be using both together, as the total adds up to more than the usage of core.
Android isn't used much at all. We also don't know why. It might be that people are using Appium in combination with cucumber-java.
Most people are using Java, in combination with JUnit or TestNg as a test framework. About half our users don't use a DI container; the other half uses Picocontainer, Spring or Guice.
Footnotes:
- 1 : With 2.0.0 the groupId has changed to io.cucumber but due to to its recent release these numbers are not representative yet.
- 2 : This is not a completely accurate representation of use. Many corporate environments use a cache to avoid overloading maven central. It is however the best we have.
See CHANGELOG.md.