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

Support for Bazel #1261

Open
gergelyfabian opened this issue Dec 1, 2022 · 12 comments
Open

Support for Bazel #1261

gergelyfabian opened this issue Dec 1, 2022 · 12 comments

Comments

@gergelyfabian
Copy link
Contributor

How could I start using Stryker4s with Scala, when using Bazel as a build system?

I see there is already support for sbt and Maven.

What could be the easiest path to add support for Bazel? What steps would be needed? (I could try contributing a solution)
Is there e.g. a way to use Stryker4s from the command line?

Thank you!

Here is an example Scala project with Bazel: https://github.com/gergelyfabian/bazel-scala-example

@gergelyfabian
Copy link
Contributor Author

The Bazel plugin I use to run Scala is https://github.com/bazelbuild/rules_scala. In case changes are necessary I could try contributing it over there too.

@gergelyfabian
Copy link
Contributor Author

Moved the conversation to Slack.

@gergelyfabian
Copy link
Contributor Author

Tried with such a stryker4s.conf:

# First, install coursier:
#   https://get-coursier.io/docs/cli-installation
# Then run Stryker4s with:
#   cs launch io.stryker-mutator::stryker4s-command-runner:latest.release
# Check for more options:
#   https://stryker-mutator.io/docs/stryker4s/configuration/

stryker4s {
  # Change to the submodule you want to test
  mutate: [ "my-module/**/main/scala/**/*.scala" ]
  scala-dialect: "2.12"
  test-runner: { command: "bazel", args: "test //my-module:all" }
}

Unfortunately this fails with a timeout exception. The issue is, that Bazel has to rebuild a significant part of the code if a new workspace is created (this is done when the code is copied), so it times out. For using Bazel we'd need to enable in-place mutation, because then Bazel caches could be reused.

StrykerJs already has such an option:
https://stryker-mutator.io/docs/stryker-js/configuration/#inplace-boolean

@gergelyfabian
Copy link
Contributor Author

Another option is to enable overriding the tmpDir in src/main/scala/stryker4s/run/MutantRunner.scala.prepareEnv(), so that we can force the tmpDir to be created in a predefined place, that would enable prebuilding the code with Bazel and be able to use the cache when running mutation tests.

@gergelyfabian
Copy link
Contributor Author

gergelyfabian commented Dec 1, 2022

I've managed to put together a version where Stryker4s can work with Bazel.

Sent some PRs as improvements (merged now):

Other details:

  • stryker uses env vars, this needs special care with Bazel, as Bazel cuts out environment vars (they do not affect test results and caching results). Need to use --test_env=ACTIVE_MUTATION to make that env var have effect on test inputs.
  • I needed to exclude MethodExpression mutations as they seemed to generate such methods that were non-existent in my codebase (e.g. for scala.util.Try)

Here is the config I used:

# Example Stryker4s configuration.
# https://stryker-mutator.io/docs/stryker4s/getting-started/
#
# Manual steps to do:
#
# First, install coursier:
#   https://get-coursier.io/docs/cli-installation
# Then run official Stryker4s with (doesn't work yet):
#   cs launch io.stryker-mutator::stryker4s-command-runner:latest.release
# Run snapshot version:
#   cs launch io.stryker-mutator:stryker4s-command-runner_2.13:0.14.3+198-b81cc5eb-SNAPSHOT -r sonatype:snapshots -- --debug
# Check for more options:
#   https://stryker-mutator.io/docs/stryker4s/configuration/

stryker4s {
  # Change to the submodule you want to test
  # Ensure you turn off fatal warnings, as stryker4s adds such code that will generate warnings
  mutate: [ "my-submodule/**/main/scala/**/MyFoo.scala" ]
  scala-dialect: "2.12"
  # Use --test_env to enable Stryker4s modify prod's behavior (it augments prod code to be able to change its behavior with env vars).
  # https://bazel.build/reference/command-line-reference#flag--test_env
  # This is better than --action_env, as built artifacts do not have to change.
  test-runner: { command: "bazel", args: "test --test_env=ACTIVE_MUTATION -- //my-submodule:my_test" }
  static-tmp-dir: true
  debug {
    log-test-runner-stdout: true
    debug-test-runner: false
  }
  excluded-mutations: ["MethodExpression"]
}

@gergelyfabian
Copy link
Contributor Author

Adding some follow up from Bazel Slack channel.

Instead of passing --test_env=ACTIVE_MUTATION to bazel, we can set up the test target with:

    env_inherit = [
        "ACTIVE_MUTATION",
    ],

And Stryker4s still works.
This enables potentially better usage of the Bazel cache.

@gergelyfabian
Copy link
Contributor Author

Link to related rules_scala feature: bazelbuild/rules_scala#1401

@hugo-vrijswijk
Copy link
Member

Thanks for the extensive research and documentation here! I've been wanting to add a FAQ to the Stryker4s docs for a while, and I think this would be a great fit for it when I get around to it :)

@gergelyfabian
Copy link
Contributor Author

gergelyfabian commented Dec 6, 2022 via email

@gergelyfabian
Copy link
Contributor Author

Updated example in #1261 (comment) after latest PR changes.

@gergelyfabian
Copy link
Contributor Author

Updated example in #1261 (comment) after PRs got merged.

@YVbakker
Copy link

will be easier after #1522

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

3 participants