-
Notifications
You must be signed in to change notification settings - Fork 30
Add cucumber-scalatest integration module #416
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
Draft
Copilot
wants to merge
12
commits into
main
Choose a base branch
from
copilot/add-cucumber-scalatest-integration
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 7 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
a98b740
Initial plan
Copilot 29adc48
Add cucumber-scalatest module and integration tests structure
Copilot c371913
Implement working CucumberSuite trait for Scalatest integration
Copilot e9b91f9
Working cucumber-scalatest integration - scenarios run successfully
Copilot c53e08e
Add cucumber-scalatest example project
Copilot 0561131
Run scalafmtAll to format code according to project standards
Copilot 80fbe29
Replace annotation with case class, simplify to single example test
Copilot 0404bce
Add tags filter support and remove junit-platform.properties
Copilot 050f442
Add unit tests for CucumberSuite integration with ScalaTest
Copilot 44465e8
Add support for parsing RuntimeOptions from properties/environment/sy…
Copilot 944e03a
Refactor CucumberSuite to parse features and scenarios as nested Scal…
Copilot 97a9fc4
Fix CucumberSuite to properly report test failures and test counts
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
125 changes: 125 additions & 0 deletions
125
cucumber-scalatest/src/main/scala/io/cucumber/scalatest/CucumberSuite.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| package io.cucumber.scalatest | ||
|
|
||
| import io.cucumber.core.options.RuntimeOptionsBuilder | ||
| import io.cucumber.core.runtime.{Runtime => CucumberRuntime} | ||
| import org.scalatest.{Args, Status, Suite} | ||
|
|
||
| import scala.annotation.nowarn | ||
|
|
||
| /** Configuration for Cucumber tests. | ||
| * | ||
| * @param features | ||
| * paths to feature files or directories (e.g., "classpath:features") | ||
| * @param glue | ||
| * packages containing step definitions (e.g., "com.example.steps") | ||
| * @param plugin | ||
| * plugins to use (e.g., "pretty", "json:target/cucumber.json") | ||
| */ | ||
| case class CucumberOptions( | ||
| features: List[String] = List.empty, | ||
| glue: List[String] = List.empty, | ||
| plugin: List[String] = List.empty | ||
| ) | ||
|
|
||
| /** A trait that allows Cucumber scenarios to be run with ScalaTest. | ||
| * | ||
| * Mix this trait into your test class and define the `cucumberOptions` value | ||
| * to configure the Cucumber runtime. | ||
| * | ||
| * Example: | ||
| * {{{ | ||
| * import io.cucumber.scalatest.{CucumberOptions, CucumberSuite} | ||
| * | ||
| * class RunCucumberTest extends CucumberSuite { | ||
| * override val cucumberOptions = CucumberOptions( | ||
| * features = List("classpath:features"), | ||
| * glue = List("com.example.stepdefinitions"), | ||
| * plugin = List("pretty") | ||
| * ) | ||
| * } | ||
| * }}} | ||
| */ | ||
| @nowarn | ||
| trait CucumberSuite extends Suite { | ||
|
|
||
| /** Override this value to configure Cucumber options. If not overridden, | ||
| * defaults will be used based on the package name. | ||
| */ | ||
| def cucumberOptions: CucumberOptions = CucumberOptions() | ||
|
|
||
| /** Runs the Cucumber scenarios. | ||
| * | ||
| * @param testName | ||
| * An optional name of one test to run. If None, all relevant tests should | ||
| * be run. | ||
| * @param args | ||
| * the Args for this run | ||
| * @return | ||
| * a Status object that indicates when all tests started by this method | ||
| * have completed, and whether or not a failure occurred. | ||
| */ | ||
| abstract override def run( | ||
| testName: Option[String], | ||
| args: Args | ||
| ): Status = { | ||
| if (testName.isDefined) { | ||
| throw new IllegalArgumentException( | ||
| "Suite traits implemented by Cucumber do not support running a single test" | ||
| ) | ||
| } | ||
|
|
||
| val runtimeOptions = buildRuntimeOptions() | ||
| val classLoader = getClass.getClassLoader | ||
|
|
||
| val runtime = CucumberRuntime | ||
| .builder() | ||
| .withRuntimeOptions(runtimeOptions) | ||
| .withClassLoader(new java.util.function.Supplier[ClassLoader] { | ||
| override def get(): ClassLoader = classLoader | ||
| }) | ||
| .build() | ||
|
|
||
| runtime.run() | ||
|
|
||
| val exitStatus = runtime.exitStatus() | ||
| if (exitStatus == 0) { | ||
| org.scalatest.SucceededStatus | ||
| } else { | ||
| throw new RuntimeException( | ||
| s"Cucumber scenarios failed with exit status: $exitStatus" | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| private def buildRuntimeOptions(): io.cucumber.core.options.RuntimeOptions = { | ||
| val packageName = getClass.getPackage.getName | ||
| val builder = new RuntimeOptionsBuilder() | ||
|
|
||
| // Add features | ||
| val features = | ||
| if (cucumberOptions.features.nonEmpty) cucumberOptions.features | ||
| else List("classpath:" + packageName.replace('.', '/')) | ||
gaeljw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| features.foreach { feature => | ||
| builder.addFeature( | ||
| io.cucumber.core.feature.FeatureWithLines.parse(feature) | ||
| ) | ||
| } | ||
|
|
||
| // Add glue | ||
| val glue = | ||
| if (cucumberOptions.glue.nonEmpty) cucumberOptions.glue | ||
| else List(packageName) | ||
|
|
||
| glue.foreach { g => | ||
| builder.addGlue(java.net.URI.create("classpath:" + g)) | ||
| } | ||
|
|
||
| // Add plugins | ||
| cucumberOptions.plugin.foreach { p => | ||
| builder.addPluginName(p) | ||
| } | ||
|
|
||
| builder.build() | ||
| } | ||
| } | ||
34 changes: 34 additions & 0 deletions
34
...s/examples-scalatest/src/main/scala/cucumber/examples/scalacalculator/RpnCalculator.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package cucumber.examples.scalacalculator | ||
|
|
||
| import scala.collection.mutable.Queue | ||
|
|
||
| sealed trait Arg | ||
|
|
||
| object Arg { | ||
| implicit def op(s: String): Op = Op(s) | ||
| implicit def value(v: Double): Val = Val(v) | ||
| } | ||
|
|
||
| case class Op(value: String) extends Arg | ||
| case class Val(value: Double) extends Arg | ||
|
|
||
| class RpnCalculator { | ||
| private val stack = Queue.empty[Double] | ||
|
|
||
| private def op(f: (Double, Double) => Double) = | ||
| stack += f(stack.dequeue(), stack.dequeue()) | ||
|
|
||
| def push(arg: Arg): Unit = { | ||
| arg match { | ||
| case Op("+") => op(_ + _) | ||
| case Op("-") => op(_ - _) | ||
| case Op("*") => op(_ * _) | ||
| case Op("/") => op(_ / _) | ||
| case Val(value) => stack += value | ||
| case _ => () | ||
| } | ||
| () | ||
| } | ||
|
|
||
| def value: Double = stack.head | ||
| } |
7 changes: 7 additions & 0 deletions
7
...s-scalatest/src/test/resources/cucumber/examples/scalacalculator/basic_arithmetic.feature
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| @foo | ||
| Feature: Basic Arithmetic | ||
|
|
||
| Scenario: Adding | ||
| # Try to change one of the values below to provoke a failure | ||
| When I add 4.0 and 5.0 | ||
| Then the result is 9.0 |
4 changes: 4 additions & 0 deletions
4
examples/examples-scalatest/src/test/resources/junit-platform.properties
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| cucumber.plugin=pretty | ||
| # Workaround for https://github.com/sbt/sbt-jupiter-interface/issues/142 | ||
gaeljw marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| # See also https://github.com/cucumber/cucumber-jvm/pull/3023 | ||
| cucumber.junit-platform.discovery.as-root-engine=false | ||
25 changes: 25 additions & 0 deletions
25
...atest/src/test/scala/cucumber/examples/scalacalculator/RpnCalculatorStepDefinitions.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| package cucumber.examples.scalacalculator | ||
|
|
||
| import io.cucumber.scala.{EN, ScalaDsl, Scenario} | ||
|
|
||
| class RpnCalculatorStepDefinitions extends ScalaDsl with EN { | ||
|
|
||
| val calc = new RpnCalculator | ||
|
|
||
| When("""I add {double} and {double}""") { (arg1: Double, arg2: Double) => | ||
| calc push arg1 | ||
| calc push arg2 | ||
| calc push "+" | ||
| } | ||
|
|
||
| Then("the result is {double}") { (expected: Double) => | ||
| assert( | ||
| math.abs(expected - calc.value) < 0.001, | ||
| s"Expected $expected but got ${calc.value}" | ||
| ) | ||
| } | ||
|
|
||
| Before("not @foo") { (scenario: Scenario) => | ||
| println(s"Runs before scenarios *not* tagged with @foo (${scenario.getId})") | ||
| } | ||
| } |
11 changes: 11 additions & 0 deletions
11
...es/examples-scalatest/src/test/scala/cucumber/examples/scalacalculator/RunCukesTest.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package cucumber.examples.scalacalculator | ||
|
|
||
| import io.cucumber.scalatest.{CucumberOptions, CucumberSuite} | ||
|
|
||
| class RunCukesTest extends CucumberSuite { | ||
| override val cucumberOptions = CucumberOptions( | ||
| features = List("classpath:cucumber/examples/scalacalculator"), | ||
| glue = List("cucumber.examples.scalacalculator"), | ||
| plugin = List("pretty") | ||
| ) | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.