Skip to content

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-shuy authored Jan 18, 2018
1 parent 234bff3 commit 83efb97
Showing 1 changed file with 87 additions and 19 deletions.
106 changes: 87 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

[![Codacy Badge](https://api.codacy.com/project/badge/Grade/244276b4573e4ae899443fa79c34822b)](https://www.codacy.com/app/daniel-shuy/scripted-scalatest-sbt-plugin?utm_source=github.com&utm_medium=referral&utm_content=daniel-shuy/scripted-scalatest-sbt-plugin&utm_campaign=badger)

| Plugin Version | SBT Version | ScalaTest Version |
| -------------- | ------------------- | ----------------- |
| 0.1.X | 0.13.X | 3.X.X |
| 0.2.X | 0.13.X, 1.X.X | 3.X.X |

A SBT plugin to use [ScalaTest](http://www.scalatest.org/) with scripted-plugin to test your SBT plugins

Traditionally, to test a SBT plugin, you had to create subprojects in `/sbt-test`, then in the subprojects, create SBT tasks to perform the testing, then specify the tasks to execute in a `test` file (see http://www.scala-sbt.org/0.13/docs/Testing-sbt-plugins.html).
Expand All @@ -14,56 +19,86 @@ This plugin leverages ScalaTest's powerful assertion system (to automatically pr

This plugin allows you to use any of ScalaTest's test [Suites](http://www.scalatest.org/user_guide/selecting_a_style), including [AsyncTestSuites](http://www.scalatest.org/user_guide/async_testing).

__Warning__: Do not use ScalaTest's [ParallelTestExecution](http://doc.scalatest.org/3.0.0/index.html#org.scalatest.ParallelTestExecution) mixin with this plugin, unless you are absolutely sure your tests have no side effects.

## Note
When executing SBT tasks in tests, use `Project.runTask(<task>, state.value)` instead of `<task>.value`. That is because calling `<task>.value` declares it as a dependency, which executes before the tests, not when the line is called.
- Do not use ScalaTest's [ParallelTestExecution](http://doc.scalatest.org/3.0.0/index.html#org.scalatest.ParallelTestExecution) mixin with this plugin. `ScriptedScalaTestSuiteMixin` runs `sbt clean` before each test, which may cause weird side effects when run in parallel.
- When executing SBT tasks in tests, use `Project.runTask(<task>, state.value)` instead of `<task>.value`. Calling `<task>.value` declares it as a dependency, which executes before the tests, not when the line is called.

## Usage

### Step 1: Include the scripted-plugin in your build

See http://www.scala-sbt.org/0.13/docs/Testing-sbt-plugins.html#step+2%3A+scripted-plugin
Add the following to your main project's `project/scripted.sbt` (create file it if doesn't exist):
```scala
libraryDependencies += { "org.scala-sbt" % "scripted-plugin" % sbtVersion.value }
```

### Step 2: Configure scripted-plugin

If you are using [sbt-cross-building](https://github.com/jrudolph/sbt-cross-building), don't add scripted-plugin to `project/scripted.sbt`, and replace `ScriptedPlugin.scriptedSettings` in `scripted.sbt` with `CrossBuilding.scriptedSettings`.
Recommended settings by SBT:

### Step 2: Create the test subproject
#### SBT 0.13 (http://www.scala-sbt.org/0.13/docs/Testing-sbt-plugins.html#step+2%3A+scripted-plugin)

```scala
// build.sbt
ScriptedPlugin.scriptedSettings
scriptedLaunchOpts := { scriptedLaunchOpts.value ++
Seq("-Xmx1024M", "-XX:MaxPermSize=256M", "-Dplugin.version=" + version.value)
}
scriptedBufferLog := false
```

If you are using [sbt-cross-building](https://github.com/jrudolph/sbt-cross-building) (SBT < 0.13.6), don't add scripted-plugin to `project/scripted.sbt`, and replace `ScriptedPlugin.scriptedSettings` in `build.sbt` with `CrossBuilding.scriptedSettings`.

#### SBT 1.X (http://www.scala-sbt.org/1.x/docs/Testing-sbt-plugins.html#step+2%3A+scripted-plugin)

```scala
// build.sbt
scriptedLaunchOpts := { scriptedLaunchOpts.value ++
Seq("-Xmx1024M", "-Dplugin.version=" + version.value)
}
scriptedBufferLog := false
```

### Step 3: Create the test subproject

Create the test subproject in `sbt-test/<test-group>/<test-name>`.

Include your plugin in the build.

See http://www.scala-sbt.org/0.13/docs/Testing-sbt-plugins.html#step+3%3A+src%2Fsbt-test
See http://www.scala-sbt.org/0.13/docs/Testing-sbt-plugins.html#step+3%3A+src%2Fsbt-test for an example.

### Step 3: Include the plugin in your build
### Step 4: Include sbt-scripted-scalatest in your build

Add the following to your `sbt-test/<test-group>/<test-name>/project/plugins.sbt`:
```scala
addSbtPlugin("com.github.daniel-shuy" % "sbt-scripted-scalatest" % "0.1.0")
addSbtPlugin("com.github.daniel-shuy" % "sbt-scripted-scalatest" % "0.2.0")
```

### Step 4: Configure `test` script
### Step 5: Configure `test` script

Put __only__ the following in the `sbt-test/<test-group>/<test-name>/test` script file:

`> scripted-scalatest`
`> scriptedScalatest`

### Step 5: Configure project settings for the plugin
### Step 6: Configure project settings for the plugin

Create a new ScalaTest Suite/Spec, mixin `ScriptedScalaTestSuiteMixin` and pass it into `scriptedScalaTestSpec`. When mixing in `ScriptedScalaTestSuiteMixin`, implement `sbtState` as `state.value`.
In `sbt-test/<test-group>/<test-name>/build.sbt`, create a new ScalaTest Suite/Spec, mixin `ScriptedScalaTestSuiteMixin` and pass it into `scriptedScalaTestSpec`. When mixing in `ScriptedScalaTestSuiteMixin`, implement `sbtState` as `state.value`.

Example:
```scala
import com.github.daniel.shuy.sbt.scripted.scalatest.ScriptedScalaTestSuiteMixin
import org.scalatest.WordSpec

scriptedScalaTestSpec := Some(new WordSpec with ScriptedScalaTestSuiteMixin {
override val sbtState: State = state.value

"my-task" should {
"do A" in {
Project.runTask(myTask, state.value)
// ...
// assert(...)
}

"do B" in {
Project.runTask(myTask, state.value)
// ...
Expand All @@ -73,9 +108,44 @@ scriptedScalaTestSpec := Some(new WordSpec with ScriptedScalaTestSuiteMixin {
})
```

Another alternative is to move the ScalaTest Suite/Spec into another file (the file must reside within the `project` folder) and instantiate it in your `build.sbt` instead. Add a constructor argument that takes in a `sbt.State`, then implement `sbtState` as that constructor argument. Pass `state.value` into the constructor when instantiating the ScalaTest Suite/Spec.

Example:
```scala
// project/ExampleSpec.scala
import com.github.daniel.shuy.sbt.scripted.scalatest.ScriptedScalaTestSuiteMixin
import org.scalatest.WordSpec
import sbt.State

class ExampleSpec(state: State) extends WordSpec with ScriptedScalaTestSuiteMixin {
override val sbtState: State = state

"my-task" should {
"do A" in {
Project.runTask(myTask, state.value)
// ...
// assert(...)
}

"do B" in {
Project.runTask(myTask, state.value)
// ...
// assert(...)
}
}
}
```

```scala
// build.sbt
scriptedScalaTestSpec := Some(new ExampleSpec(state.value))
```

See [Settings](#settings) for other configurable settings.

### Step 6: Use the scripted-plugin as usual
### Step 7: Use the scripted-plugin as usual

Append `-SNAPSHOT` to the main project `version` before running `scripted-plugin`.

Eg. Run `sbt scripted` on the main project to execute all tests.

Expand All @@ -92,7 +162,7 @@ Eg. Run `sbt scripted` on the main project to execute all tests.

| Task | Description |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| scripted-scalatest | Executes all test configured in `scriptedScalaTestSpec`. This task must be [configured for scripted-plugin to run in the `test` script file](#step-4-configure-test-script). |
| scripted-scalatest | Executes all test configured in `scriptedScalaTestSpec`. This task must be [configured for scripted-plugin to run in the `test` script file](#step-5-configure-test-script). |

## Known Issues

Expand All @@ -102,8 +172,6 @@ Currently, mixing in `BeforeAndAfter` into your ScalaTest Suite/Spec and impleme

I would like to create test cases for this plugin, ideally eventually using this plugin itself. Unfortunately, I just can't seem to figure out how to convert `scripted` from an `InputKey` into a `TaskKey` so that I can execute it with `Project.runTask`. I keep getting errors no matter what arguments I pass into `scripted.toTask`. I'll be really grateful if anyone can point me in the right direction.

When SBT 1.0.x is released, it should be possible to automatically generate the `test` script file, removing the need for [Step 4](#step-4-configure-test-script).

## Licence

Copyright 2017 Daniel Shuy
Expand Down

0 comments on commit 83efb97

Please sign in to comment.