Skip to content

Commit

Permalink
Improve documentation; upgrade Scala (#52)
Browse files Browse the repository at this point in the history
* drop duplicate scalafmt
* clarify requirements
* clarify suites and test methods
* enhance doc
* upgrade the scalas
  • Loading branch information
mcanlas authored Aug 15, 2020
1 parent 17110fe commit 8c0f6e4
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 30 deletions.
65 changes: 47 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ which generally keeps tests cleaner / clearer.

## API

Weaver's core framework provides two primary types of testing suites.

| Suite name | Use case |
| --- | --- |
| `SimpleIOSuite` | Each test is a standalone `IO` action
| `IOSuite` | Each test needs access to a shared `Resource`

### Suites

#### SimpleIOSuite
Expand All @@ -62,55 +69,74 @@ import cats.effect._
// Suites must be "objects" for them to be picked by the framework
object MySuite extends SimpleIOSuite {

// A test for non-effectful (pure) functions
pureTest("hello pure"){
pureTest("non-effectful (pure) test"){
expect("hello".size == 6)
}

val random = IO(java.util.UUID.randomUUID())
private val random = IO(java.util.UUID.randomUUID())

// A test for side-effecting functions
simpleTest("hello side-effects") {
simpleTest("test with side-effects") {
for {
x <- random
y <- random
} yield expect(x != y)
}

// A test with logs
loggedTest("hello logs"){ log =>
loggedTest("test with side-effects and a logger"){ log =>
for {
x <- random
_ <- log.info(s"x : $x")
y <- random
_ <- log.info(s"y : $y")
} yield expect(x != y)
}

}
```

#### IOSuite

The `IOSuite` constructs the given resource once for all tests in the suite.

```scala
import weaver.IOSuite
import cats.effect._

// Same as SimpleIOSuite, but supports sharing a resource across tests
object MySuite extends IOSuite {

override type Res = AmazonDynamodb
def sharedResource : Resource[IO, AmazonDynamodb] = Resource.make(...)

// A test that uses the shared resource
test("hello resource"){ (ddb : AmazonDynamodb, log : Log[IO]) =>
// ...
type Res = Int

def sharedResource : Resource[IO, Int] = Resource
.make(
IO(println("Making resource"))
.as(123)
)(n => IO(println(s"Closing resource $n")))

test("test, but resource not visible"){
expect(123 == 123)
}

test("test with resource"){ n =>
expect(n == 123)
}

test("test with resource and a logger"){ (n, log) =>
log.info("log was available")
expect(n == 123)
}


}
```

#### Other suites

Weaver also includes support for `ZIO`-based suites via the optional `weaver-zio` dependency.

| Alias | Suite name | Provided by | Use case |
| --- | --- | --- | --- |
| `SimpleIOSuite` | `SimpleMutableIOSuite` | `weaver-framework` | Each test is a standalone `IO` action
| `IOSuite` | `MutableIOSuite` | `weaver-framework` | Each test needs access to a shared `Resource`
| `SimpleZIOSuite` | `SimpleMutableZIOSuite` | `weaver-zio` | Each test is a standalone `ZIO` action
| `ZIOSuite[R]` | `MutableZIOSuite[R]` | `weaver-zio` | Each test needs access to a shared `ZLayer`

### Expectations (assertions)

#### Building expectations
Expand Down Expand Up @@ -184,7 +210,10 @@ Contributions are most welcome !

### Development requirements

This repository uses [Git LFS](https://git-lfs.github.com/). To install for Mac using `brew`:
:warning: This repository uses [Git LFS](https://git-lfs.github.com/). Having it installed is required for
`git checkout` to work properly.

To install for Mac using `brew`:

```bash
brew install git-lfs
Expand Down
9 changes: 7 additions & 2 deletions modules/core/src/weaver/Log.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@ object Log {
// Logger that doesn't do anything
def nop[F[_]: Applicative]: Log[F] = _ => Applicative[F].unit

// Logger that collects the entries in a referential-transparent variable
// containing a collection
/**
* Builds a logger that collects to a referential-transparent variable
*
* @param ref A reference to the logger
* @tparam F Effect type
* @tparam L Logging collection type
*/
def collected[F[_], L[_]: MonoidK: Applicative](
ref: Ref[F, L[Entry]]): Log[F] = new Log[F] {
implicit val monoid: Monoid[L[Entry]] = MonoidK[L].algebra[Entry]
Expand Down
9 changes: 5 additions & 4 deletions modules/framework/src/weaver/framework/TestFramework.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,11 @@ object TestFramework {
}

trait WeaverFingerprint extends SubclassFingerprint {
def unapply(taskDef: TaskDef): Option[TaskDef] = taskDef.fingerprint match {
case sf: SubclassFingerprint if fingerprintMatches(sf) => Some(taskDef)
case _ => None
}
def unapply(taskDef: TaskDef): Option[TaskDef] =
taskDef.fingerprint() match {
case sf: SubclassFingerprint if fingerprintMatches(sf) => Some(taskDef)
case _ => None
}

private def fingerprintMatches(sf: SubclassFingerprint): Boolean = {
sf.isModule() == this.isModule() &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ object ZIOSuiteTest extends ZIOSuite[KVStore] {
(_, events) <- DogFood.runSuite(testSuite).to[Task]
} yield {
val event = events.headOption.get
expect(event.status == Status.Error) and
expect(event.status() == Status.Error) and
expect(event.throwable().get().getMessage == "oh no")
}
}
Expand All @@ -55,7 +55,7 @@ object ZIOSuiteTest extends ZIOSuite[KVStore] {
test("fail properly on failed expectations") {
for {
(_, events) <- DogFood.runSuite(TestWithFailedExpectation).to[Task]
} yield expect(events.headOption.get.status == Status.Failure)
} yield expect(events.headOption.get.status() == Status.Failure)
}

object TestWithExceptionInTest extends SimpleZIOSuite {
Expand Down
6 changes: 3 additions & 3 deletions project/WeaverPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ object WeaverPlugin extends AutoPlugin {
override def requires = plugins.JvmPlugin
override def trigger = allRequirements

lazy val scala212 = "2.12.11"
lazy val scala213 = "2.13.2"
lazy val scala212 = "2.12.12"
lazy val scala213 = "2.13.3"
lazy val supportedScalaVersions = List(scala212, scala213)

/** @see [[sbt.AutoPlugin]] */
Expand Down Expand Up @@ -90,7 +90,6 @@ object WeaverPlugin extends AutoPlugin {
"-Xlint:inaccessible", // Warn about inaccessible types in method signatures.
"-Xlint:infer-any", // Warn when a type argument is inferred to be `Any`.
"-Xlint:missing-interpolator", // A string literal appears to be missing an interpolator id.
"-Xlint:nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'.
"-Xlint:nullary-unit", // Warn when nullary methods return Unit.
"-Xlint:option-implicit", // Option.apply used implicit view.
"-Xlint:package-object-classes", // Class or object defined in package object.
Expand All @@ -115,6 +114,7 @@ object WeaverPlugin extends AutoPlugin {
Seq(
"-Xfuture", // Turn on future language features.
"-Xlint:by-name-right-associative", // By-name parameter of right associative operator.
"-Xlint:nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'.
"-Xlint:unsound-match", // Pattern match may not be typesafe.
"-Yno-adapted-args", // Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver.
"-Ypartial-unification", // Enable partial unification in type constructor inference
Expand Down
1 change: 0 additions & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.0.0")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.1")
addSbtPlugin("com.dwijnand" % "sbt-dynver" % "4.1.1")
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.4")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.3.0")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2")
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.6.1")
addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.2.5")

0 comments on commit 8c0f6e4

Please sign in to comment.