### Per-Test Setup and Teardown with utestBeforeEach and utestAfterEach Source: https://context7.com/com-lihaoyi/utest/llms.txt Override `utestBeforeEach(path)` and `utestAfterEach(path)` to run setup and teardown code around every individual test. The `path` argument provides the sequence of test names leading to the current test. Ensure that any resources set up in `utestBeforeEach` are properly cleaned up in `utestAfterEach`. ```scala import utest._ class BeforeAfterEachDemo extends TestSuite { var db: String = _ override def utestBeforeEach(path: Seq[String]): Unit = { db = s"fresh-db-for-${path.mkString(".")}" println(s"Setup: $db") } override def utestAfterEach(path: Seq[String]): Unit = { println(s"Teardown: $db") db = null } val tests = Tests { test("test1") { assert(db != null) db } test("test2") { assert(db.startsWith("fresh-db")) } } } // Each test gets its own fresh `db` value; after each test db is nulled out. // Output: // Setup: fresh-db-for-test1 // + BeforeAfterEachDemo.test1 0ms fresh-db-for-test1 // Teardown: fresh-db-for-test1 // Setup: fresh-db-for-test2 // + BeforeAfterEachDemo.test2 0ms // Teardown: fresh-db-for-test2 ``` -------------------------------- ### Custom Framework with Setup/Teardown Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Extend `utest.runner.Framework` to define custom setup and teardown logic that runs once per test run. This is useful for expensive initialization or cleanup tasks. ```scala class CustomFramework extends utest.runner.Framework{ override def setup() = { println("Setting up CustomFramework") } override def teardown() = { println("Tearing down CustomFramework") } } ``` -------------------------------- ### Example Test Output Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Sample output from running tests, showing passed, failed, and errored tests with details. ```text -------------------------------- Running Tests -------------------------------- Setting up CustomFramework X example.HelloTests.test1 4ms java.lang.Exception: test1 example.HelloTests$.$anonfun$tests$2(HelloTests.scala:7) + example.HelloTests.test2.inner 0ms 1 X example.HelloTests.test3 0ms java.lang.IndexOutOfBoundsException: 10 scala.collection.LinearSeqOptimized.apply(LinearSeqOptimized.scala:63) scala.collection.LinearSeqOptimized.apply$(LinearSeqOptimized.scala:61) scala.collection.immutable.List.apply(List.scala:86) example.HelloTests$.$anonfun$tests$5(HelloTests.scala:16) Tearing down CustomFramework Tests: 3, Passed: 1, Failed: 2 ``` -------------------------------- ### SBT and Mill Setup for uTest Source: https://context7.com/com-lihaoyi/utest/llms.txt Add uTest as a test dependency and register its test framework in SBT or Mill. ```scala // build.sbt (SBT) libraryDependencies += "com.lihaoyi" %% "utest" % "0.10.0-RC1" % "test" testFrameworks += new TestFramework("utest.runner.Framework") ``` ```scala // build.mill (Mill) def mvnDeps = Seq(mvn"com.lihaoyi::utest:0.10.0-RC1") def testFramework = "utest.runner.Framework" ``` -------------------------------- ### Define a Basic uTest Test Suite Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Create a `TestSuite` in your `src/test/scala/` folder. Define tests using the `Tests` object and individual `test` blocks. Examples include a failing test, a passing test, and a test that throws an exception. ```scala package example import utest._ class HelloTests extends TestSuite{ val tests = Tests{ test("test1"){ throw new Exception("test1") } test("test2"){ 1 } test("test3"){ val a = List[Byte](1, 2) a(10) } } } ``` -------------------------------- ### Define and Run Tests Standalone Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Defines a test suite using `Tests` and runs it using `TestRunner.run`. This is the basic setup for executing tests programmatically. ```scala import utest._ val tests = Tests{ test("test1"){ // throw new Exception("test1") } test("test2"){ test("inner"){ 1 } } test("test3"){ val a = List[Byte](1, 2) // a(10) } } // Run and return results val results1 = TestRunner.run(tests) ``` -------------------------------- ### Implement DRY Tests with TestPath and Git Cloning Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md This example demonstrates using the TestPath implicit to dynamically clone Git repositories based on test names, keeping tests DRY and synchronized. It requires sys.process and Files/Paths imports. ```scala def checkRepo(filter: String => Boolean = _ => true) (implicit testPath: utest.framework.TestPath) = { val url = "https://github.com/" + testPath.value.last import sys.process._ val name = url.split("/").last if (!Files.exists(Paths.get("target", "repos", name))){ println("CLONING") Seq("git", "clone", url, "target/repos/"+name, "--depth", "1").! } checkDir("target/repos/"+name, filter) } "lihaoyi/fastparse" - checkRepo() "scala-js/scala-js" - checkRepo() "scalaz/scalaz" - checkRepo() "milessabin/shapeless" - checkRepo() "akka/akka"- checkRepo() "lift/framework" - checkRepo() "playframework/playframework" - checkRepo() "PredictionIO/PredictionIO" - checkRepo() "apache/spark" - checkRepo() ``` -------------------------------- ### Custom Test Framework with Lifecycle Hooks and Formatting Source: https://context7.com/com-lihaoyi/utest/llms.txt Subclass `utest.runner.Framework` to customize per-run lifecycle hooks (setup, teardown) and output formatting (summary threshold, stack frame highlighting, color, truncation). Register with SBT using `testFrameworks`. ```scala // In test sources or a separate module class MyFramework extends utest.runner.Framework { // Run once before any tests override def setup(): Unit = { println("Connecting to test database...") } // Run once after all tests override def teardown(): Unit = { println("Closing test database connection.") } // Show summary only when more than 50 tests run override def showSummaryThreshold = 50 // Highlight stack frames from your own code override def exceptionStackFrameHighlighter(s: StackTraceElement): Boolean = s.getClassName.startsWith("com.mycompany.") // Disable colors (e.g., for CI logs) override def formatColor: Boolean = false // Truncate printed values at 20 lines override def formatTruncateHeight: Int = 20 } // build.sbt // testFrameworks += new TestFramework("com.mycompany.MyFramework") ``` -------------------------------- ### Separate Setup Tests with Mutable Variables Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Demonstrates how mutable variables defined within a `Tests` block are scoped independently for each nested test, preventing inter-test interference. ```scala package example import utest._ class SeparateSetupTests extends TestSuite{ val tests = Tests{ var x = 0 test("outer1"){ x += 1 test("inner1"){ x += 2 assert(x == 3) // += 1, += 2 x } test("inner2"){ x += 3 assert(x == 4) // += 1, += 3 x } } test("outer2"){ x += 4 test("inner3"){ x += 5 assert(x == 9) // += 4, += 5 x } } } } ``` -------------------------------- ### Custom Exception Stack Frame Highlighting Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Customize which stack frames are highlighted in test failure tracebacks by overriding the `exceptionStackFrameHighlighter` method. This example highlights frames originating from `utest.` classes. ```scala class CustomFramework extends utest.runner.Framework{ override def exceptionStackFrameHighlighter(s: StackTraceElement) = { s.getClassName.contains("utest.") } } ``` -------------------------------- ### Shared Fixtures Across Tests Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Illustrates how mutable variables defined outside the `Tests` block are shared across all test invocations, allowing for expensive setup to be initialized only once. ```scala package example import utest._ class SharedFixturesTests extends TestSuite{ var x = 0 val tests = Tests{ test("outer1"){ x += 1 test("inner1"){ x += 2 assert(x == 3) // += 1, += 2 x } test("inner2"){ x += 3 assert(x == 7) // += 1, += 2, += 1, += 3 x } } test("outer2"){ x += 4 test("inner3"){ x += 5 assert(x == 16) // += 1, += 2, += 1, += 3, += 4, += 5 x } } } } ``` -------------------------------- ### Run Tests with sbt Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Execute all tests in a project using the sbt test command. ```text sbt myproject/test ``` -------------------------------- ### Running Specific Tests with SBT Source: https://context7.com/com-lihaoyi/utest/llms.txt uTest supports a uniform query syntax for running specific tests, groups, or cross-suite subsets from the command line using SBT. ```bash # Run all tests in a suite sbt 'myproject/test-only -- example.NestedTests' # Run a specific test by full path sbt 'myproject/test-only -- example.NestedTests.outer1.inner1' # Run multiple specific tests using brace syntax sbt 'myproject/test-only -- example.NestedTests.outer1.{inner1,inner2}' # Run across multiple suites sbt 'myproject/test-only -- example.{HelloTests,NestedTests}' ``` -------------------------------- ### Bare Test Definitions with Logic Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Demonstrates defining tests using bare `test {...}` or `test - ...` syntax, suitable for tests with inline logic or calls to helper functions. ```scala test("parsing"){ def check(frag: fansi.Str) = { val parsed = fansi.Str(frag.render) assert(parsed == frag) parsed } test - check(fansi.Color.True(255, 0, 0)("lol")) test - check(fansi.Color.True(1, 234, 56)("lol")) test - check(fansi.Color.True(255, 255, 255)("lol")) test{ (for(i <- 0 to 255) yield check(fansi.Color.True(i,i,i)("x"))).mkString } test{ check( "#" + fansi.Color.True(127, 126, 0)("lol") + "omg" + fansi.Color.True(127, 126, 0)("wtf") ) } test{ check(square(for(i <- 0 to 255) yield fansi.Color.True(i,i,i))) } } ``` -------------------------------- ### Run Multiple Test Suites with sbt Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Selectively run multiple distinct test suites by listing them within the brace expansion syntax. This is useful for running related but separate suites. ```sh sbt 'myproject/test-only -- example.{HelloTests,NestedTests}' ``` -------------------------------- ### Run TestSuite Object Standalone Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Demonstrates running a `TestSuite` object directly, utilizing its embedded configuration for execution and output formatting. ```scala // Run `TestSuite` object directly without using SBT, and use // its configuration for execution and output formatting object MyTestSuite extends TestSuite{ val tests = Tests{ test("test1"){ // throw new Exception("test1") } test("test2"){ test("inner"){ 1 } } test("test3"){ val a = List[Byte](1, 2) // a(10) } } } val results4 = TestRunner.runAndPrint( MyTestSuite.tests, "MyTestSuiteB", executor = MyTestSuite, formatter = MyTestSuite ) ``` -------------------------------- ### Output Formatting Options Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Configure various aspects of test output formatting, including colorization, truncation, wrapping, and specific color schemes for different output elements like values, exceptions, and results. ```scala def formatColor: Boolean = true def formatTruncateHeight: Int = 15 def formatWrapWidth: Int = 100 def formatValue(x: Any) = testValueColor(x.toString) def toggledColor(t: utest.shaded.fansi.Attrs) = if(formatColor) t else utest.shaded.fansi.Attrs.Empty def testValueColor = toggledColor(utest.shaded.fansi.Color.Blue) def exceptionClassColor = toggledColor(utest.shaded.fansi.Underlined.On ++ utest.shaded.fansi.Color.LightRed) def exceptionMsgColor = toggledColor(utest.shaded.fansi.Color.LightRed) def exceptionPrefixColor = toggledColor(utest.shaded.fansi.Color.Red) def exceptionMethodColor = toggledColor(utest.shaded.fansi.Color.LightRed) def exceptionPunctuationColor = toggledColor(utest.shaded.fansi.Color.Red) def exceptionLineNumberColor = toggledColor(utest.shaded.fansi.Color.LightRed) def exceptionStackFrameHighlighter(s: StackTraceElement) = true def formatResultColor(success: Boolean) = toggledColor( if (success) utest.shaded.fansi.Color.Green else utest.shaded.fansi.Color.Red ) def formatMillisColor = toggledColor(utest.shaded.fansi.Bold.Faint) ``` -------------------------------- ### Run and Print Streaming Output Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Executes tests and prints streaming output using the default formatter. This is useful for observing test progress as it happens. ```scala // Run, return results, and print streaming output with the default formatter val results2 = TestRunner.runAndPrint( tests, "MyTestSuiteA" ) ``` -------------------------------- ### Running Specific Tests with Mill Source: https://context7.com/com-lihaoyi/utest/llms.txt uTest supports a uniform query syntax for running specific tests, groups, or cross-suite subsets from the command line using Mill. ```bash # Mill equivalents ./mill myproject.test example.NestedTests.outer1.inner1 ./mill myproject.test 'example.NestedTests.outer1.{inner1,inner2}' ``` -------------------------------- ### Framework Configuration Methods Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Override methods on `utest.runner.Framework` to control various aspects of test execution and reporting, including summary display thresholds and logger usage. ```scala def setup() = () /** * Override to run code after tests finish running. Useful for shutting * down daemon processes, closing network connections, etc. */ def teardown() = () /** * How many tests need to run before uTest starts printing out the test * results summary and test failure summary at the end of a test run. For * small sets of tests, these aren't necessary since all the output fits * nicely on one screen; only when the number of tests gets large and their * output gets noisy does it become valuable to show the clean summaries at * the end of the test run. */ def showSummaryThreshold = 30 /** * Whether to use SBT's test-logging infrastructure, or just println. * * Defaults to println because SBT's test logging doesn't seem to give us * anything that we want, and does annoying things like making a left-hand * gutter and buffering input by default */ def useSbtLoggers = false def resultsHeader = DefaultFormatters.resultsHeader def failureHeader = DefaultFormatters.failureHeader def startHeader(path: String) = DefaultFormatters.renderBanner("Running Tests" + path) ``` -------------------------------- ### Run Tests in uTest Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Tests can be run using various selectors, including fully qualified names, specific test paths, or groups of tests. ```scala foo.BarTests ``` ```scala foo.BarTests.baz.qux ``` ```scala foo.BarTests.{baz,qux} ``` ```scala foo.{BarTests,BazTests} ``` -------------------------------- ### Run Explicitly Selected Tests with sbt and mill Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Utilize brace expansion `{foo,bar}` to specify exact tests or test groups to run. This allows for precise control over test execution. ```sh sbt 'myproject/test-only -- example.NestedTests.outer1.{inner1,inner2}' ``` ```sh ./mill myProject.test 'example.NestedTests.outer1.{inner1,inner2}' ``` ```sh sbt 'myproject/test-only -- example.NestedTests.{outer1.inner1,outer2.inner3}' ``` ```sh ./mill myProject.test 'example.NestedTests.{outer1.inner1,outer2.inner3}' ``` ```sh sbt 'myproject/test-only -- example.NestedTests.{outer1.inner1,outer2}' ``` ```sh ./mill myProject.test 'example.NestedTests.{outer1.inner1,outer2}' ``` -------------------------------- ### Run Groups of Tests Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Execute a group of tests by providing the path to the enclosing block that contains them. ```sh sbt 'myproject/test-only -- example.NestedTests.outer1' ./mill myProject.test example.NestedTests.outer1 ``` -------------------------------- ### Run Individual Tests with sbt Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Execute specific tests using their full path with the `sbt test-only` command. The test selector can be wrapped in quotes for paths with special characters. ```sh sbt 'myproject/test-only -- example.NestedTests.outer1.inner1' sbt 'myproject/test-only -- example.NestedTests.outer2.inner2' sbt 'myproject/test-only -- example.NestedTests.outer2.inner3' ``` ```sh sbt 'myproject/test-only -- "example.NestedTests.segment with spaces.inner"' ``` -------------------------------- ### Run Specific Tests with SBT Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Use SBT to run specific tests or groups of tests by their fully qualified names or by using curly braces for multiple selections. ```shell sbt 'myproject/test-only -- example.{HelloTests.test1,NestedTests.outer2}' ``` ```shell sbt 'myproject/test-only -- {example.HelloTests.test1,example.NestedTests.outer2}' ``` -------------------------------- ### Run Tests with Mill Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Execute all tests in a project using the Mill build tool. ```text ./mill myproject.test ``` -------------------------------- ### Scala-Native Link Stubs Configuration Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md For Scala-Native projects using uTest, enable `nativeLinkStubs` in your build configuration. ```scala nativeLinkStubs := true ``` -------------------------------- ### Verify String Content with assertGoldenFile Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Use assertGoldenFile to compare a String with file content and update the file when UTEST_UPDATE_GOLDEN_TESTS=1. Non-existent files are treated as empty strings. Only supported on Scala-JVM. ```scala test("test"){ val expected = """I am cow |Hear me moo |I weigh twice as much as you |And I look good on the barbecue""" assertGoldenFile(expected, java.nio.file.Path.of("/Users/lihaoyi/Github/utest/hello.txt")) } ``` -------------------------------- ### Forwarding Tests to Helper Methods Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Shows how to define tests that simply forward execution to a separate helper method, useful for organizing test logic. ```scala test("test1") - processFileAndCheckOutput("input1.txt", "expected1.txt") test("test2") - processFileAndCheckOutput("input2.txt", "expected2.txt") test("test3") - processFileAndCheckOutput("input3.txt", "expected3.txt") ``` -------------------------------- ### Test Suites as Classes in uTest Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Test suites can now be defined as `class`es, which is the recommended style for better scoping and encapsulation. `object`s are still supported for backward compatibility. ```scala class MyTests extends TestSuite ``` -------------------------------- ### Run All Tests in a Suite with sbt and mill Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Execute all tests belonging to a specified test suite. This is useful for running a complete suite of related tests. ```sh sbt 'myproject/test-only -- example.NestedTests' ``` ```sh ./mill myProject.test example.NestedTests ``` -------------------------------- ### Custom Executor and Formatter Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Runs tests with a custom executor for before/after logic and a custom formatter. This allows fine-grained control over test execution and output. ```scala // Run, return results, and print output with custom formatter and executor val results3 = TestRunner.runAndPrint( tests, "MyTestSuiteA", executor = new utest.framework.Executor{ override def utestWrap(path: Seq[String], runBody: => Future[Any]) (implicit ec: ExecutionContext): Future[Any] = { println("Getting ready to run " + path.mkString(".")) utestBeforeEach() runBody.andThen { case _ => utestAfterEach() } } }, formatter = new utest.framework.Formatter{ override def formatColor = false } ) ``` -------------------------------- ### Suite Teardown Hook with utestAfterAll Source: https://context7.com/com-lihaoyi/utest/llms.txt Override `utestAfterAll()` to execute code once after all tests in the suite have completed. Global initialization can be simulated by placing code directly in the class body. ```scala import utest._ class BeforeAfterAllDemo extends TestSuite { // beforeAll equivalent: code in the class body println("Suite starting up") val sharedResource = "expensive-connection" override def utestAfterAll(): Unit = { println(s"Suite done, closing: $sharedResource") } val tests = Tests { test("uses shared resource") { assert(sharedResource == "expensive-connection") } test("also uses shared resource") { assert(sharedResource.nonEmpty) } } } ``` -------------------------------- ### Run All Tests in a Package with sbt and mill Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Run all tests within a given package, including tests in nested suites. This provides a broader test execution scope. ```sh sbt 'myproject/test-only -- example' ``` ```sh ./mill myProject.test example ``` -------------------------------- ### Snapshot Testing: assertGoldenFolder Source: https://context7.com/com-lihaoyi/utest/llms.txt Recursively compares directory trees. Reports added, removed, or changed files with diffs. Updates the golden folder when run with UTEST_UPDATE_GOLDEN_TESTS=1. Ideal for comparing generated file structures. ```scala import utest._ import java.nio.file.Path class GoldenFolderDemo extends TestSuite { val tests = Tests { test("generated folder matches golden") { val outputDir = Path.of("out/generated") val goldenDir = Path.of("test/resources/golden-output") assertGoldenFolder(outputDir, goldenDir) // Reports added/removed/changed files with diffs // Set UTEST_UPDATE_GOLDEN_TESTS=1 to update golden folder in place } } } ``` -------------------------------- ### Golden Folder Testing in uTest Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Added support for `assertGoldenFolder` for golden testing scenarios involving entire folders. ```scala assertGoldenFolder ``` -------------------------------- ### SBT Configuration for Custom Framework Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Configure SBT to use your custom test framework by specifying its class name in the `testFrameworks` setting. ```scala testFrameworks += new TestFramework("test.utest.CustomFramework") ``` -------------------------------- ### Programmatic Test Execution with TestRunner Source: https://context7.com/com-lihaoyi/utest/llms.txt Execute tests programmatically without SBT/Mill. Use `TestRunner.run` for silent collection, `TestRunner.runAndPrint` for streaming output, and `TestRunner.runAndPrintAsync` for asynchronous execution. `renderResults` formats a summary. ```scala import utest._ import utest.framework.{Executor, Formatter} val tests = Tests { test("add") { assert(1 + 1 == 2); 2 } test("greet") { "hello world" } test("fail") { throw new Exception("!") } } // Run silently and collect results val results = TestRunner.run(tests) // Run and stream output to stdout val results2 = TestRunner.runAndPrint( tests, label = "MySuite" ) // Run asynchronously import scala.concurrent.ExecutionContext.Implicits.global val futureResults = TestRunner.runAndPrintAsync(tests, "MySuiteAsync") // Render a combined summary and get pass/fail counts val (summary, successes, failures) = TestRunner.renderResults( Seq("MySuite" -> results, "MySuiteAsync" -> results2) ) println(summary.plainText) if (failures > 0) sys.exit(1) ``` -------------------------------- ### Snapshot Testing: assertGoldenFile Source: https://context7.com/com-lihaoyi/utest/llms.txt Compares a String value against a file on disk. Updates the file when run with UTEST_UPDATE_GOLDEN_TESTS=1. Use for string-based outputs like logs or generated text files. ```scala import utest._ import java.nio.file.Path class GoldenFileDemo extends TestSuite { val tests = Tests { test("output matches golden file") { val generated = "line1\nline2\nline3" assertGoldenFile( generated, Path.of("test/resources/expected-output.txt") ) // On mismatch, prints a diff and asks to re-run with UTEST_UPDATE_GOLDEN_TESTS=1 } } } ``` -------------------------------- ### Arrow Asserts for Concise Equality Checks Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Use `a ==> b` as a shorthand for `assert(a == b)`. This provides a clean syntax for equality assertions, suitable for documentation. ```scala 1 ==> 1 // passes Array(1, 2, 3) ==> Array(1, 2, 3) // passes try{ 1 ==> 2 // throws }catch{case e: java.lang.AssertionError => e } ``` -------------------------------- ### Smart Asserts with Debugging Information Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Utilize uTest's macro-powered smart asserts for enhanced debugging. When an assert fails, it prints the names, types, and values of local variables used in the failed expression. It also wraps exceptions to preserve the original stack trace. ```scala val x = 1 val y = "2" assert(x > 0) assert(x == y) // utest.AssertionError: x == y // x: Int = 1 // y: String = 2 assertAll( // Helper to perform multiple asserts at once x > 0, x == y ) ``` ```scala val x = 1L val y = 0L assert(x / y == 10) // utest.AssertionError: assert(x / y == 10) // caused by: java.lang.ArithmeticException: / by zero // x: Long = 1 // y: Long = 0 ``` -------------------------------- ### Run Individual Tests with Mill Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Execute specific tests using their full path with the Mill command. Test selectors can be wrapped in quotes for paths with special characters. ```sh ./mill myProject.test example.NestedTests.outer1.inner1 ./mill myProject.test example.NestedTests.outer2.inner2 ./mill myProject.test example.NestedTests.outer2.inner3 ``` ```sh ./mill myProject.test "example.NestedTests.segment with spaces.inner" ``` -------------------------------- ### Implement Before/After Each Test Logic in uTest Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Override utestBeforeEach and utestAfterEach methods to execute code before and after each test. These methods are invoked within utestWrap's body callback. ```scala package example import utest._ object BeforeAfterEachTest extends TestSuite { var x = 0 override def utestBeforeEach(path: Seq[String]): Unit = { println(s"on before each x: $x") x = 0 } override def utestAfterEach(path: Seq[String]): Unit = println(s"on after each x: $x") val tests = Tests{ test("outer1"){ x += 1 test("inner1"){ x += 2 assert(x == 3) // += 1, += 2 x } test("inner2"){ x += 3 assert(x == 4) // += 1, += 3 x } } test("outer2"){ x += 4 test("inner3"){ x += 5 assert(x == 9) // += 4, += 5 x } } } } ``` -------------------------------- ### Add uTest Dependency for SBT Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Add the uTest library dependency to your `build.sbt` file for Scala-JVM, Scala.js, or Scala-Native projects. Ensure to include the test framework. ```scala libraryDependencies += "com.lihaoyi" %% "utest" % "0.10.0-RC1" % "test" // Scala-JVM libraryDependencies += "com.lihaoyi" %%% "utest" % "0.10.0-RC1" % "test" // Scala.js or Scala-Native testFrameworks += new TestFramework("utest.runner.Framework") ``` -------------------------------- ### Defining a Test Suite with TestSuite and Tests Source: https://context7.com/com-lihaoyi/utest/llms.txt Define a `tests` val containing a `Tests { ... }` block with `test("name"){ ... }` calls. Test suites can be classes or objects. ```scala import utest._ class HelloTests extends TestSuite { val tests = Tests { test("addition") { assert(1 + 1 == 2) 1 + 1 // returned value is printed on success } test("strings") { val s = "hello" assert(s.length == 5) s } test("failure example") { throw new Exception("intentional failure") } } } ``` -------------------------------- ### Define a Test Block in uTest Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Use the `test` keyword to define a block of tests. This syntax is uniform for delimiting and grouping tests together. ```scala test("test") { ... } ``` -------------------------------- ### Render Test Results Summary Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Renders the standard summary reports after a test run. This includes calculating successes and failures, and can be used to determine the overall test outcome. ```scala // Show summary and exit val (summary, successes, failures) = TestRunner.renderResults( Seq( "MySuiteA" -> results1, "MySuiteA" -> results2, "MySuiteA" -> results3, "MySuiteB" -> results4 ) ) if (failures > 0) sys.exit(1) ``` -------------------------------- ### Run Asynchronous Tests with uTest Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Define and run asynchronous tests using Futures. The `runAsync` method returns a Future of the results, while `run` waits for futures to complete. Scala.js has limitations with `run` on async tests. ```scala val tests = Tests { test("testSuccess"){ Future { assert(true) } } test("testFail"){ Future { assert(false) } } test("normalSuccess"){ assert(true) } test("normalFail"){ assert(false) } } TestRunner.runAsync(tests).map { results => val leafResults = results.leaves.toSeq assert(leafResults(0).value.isSuccess) // root assert(leafResults(1).value.isSuccess) // testSuccess assert(leafResults(2).value.isFailure) // testFail assert(leafResults(3).value.isSuccess) // normalSuccess } ``` -------------------------------- ### Nested Test Execution Output Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Output showing the execution of nested tests, including successful tests and their return values. ```text ------------------------------- Running Tests ------------------------------- + example.NestedTests.outer1.inner1 21ms (1,2) + example.NestedTests.outer1.inner2 0ms + example.NestedTests.outer2.inner3 0ms ``` -------------------------------- ### Custom Test Wrapping in uTest Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Define a custom test wrapper function like myTest to initialize and teardown resources for test cases. This function can optionally accept a TestPath implicit. ```scala def myTest[T](func: Int => T) = { val fixture = 1337 // initialize some value val res = func(fixture) // make the value available in the test case assert(fixture == 1337) // properly teardown the value later res } test("test") - myTest{ fixture => // do stuff with fixture } ``` -------------------------------- ### Implement After All Test Suite Logic in uTest Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Override the utestAfterAll method to execute code after the entire test suite has completed. Code in the object body runs before all tests. ```scala package example import utest._ object BeforeAfterAllSimpleTests extends TestSuite { println("on object body, aka: before all") override def utestAfterAll(): Unit = { println("on after all") } val tests = Tests { test("outer1"){ test("inner1"){ 1 } test("inner2"){ 2 } } } } ``` -------------------------------- ### Avoid Dynamic Test Generation in Loops Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Demonstrates how to avoid defining tests within loops or conditional statements, as uTest requires statically known test structures. ```scala // Doesn't work! val tests = Tests{ for(fileName <- Seq("hello", "world", "i", "am", "cow")){ fileName - { // lots of code using fileName } } } ``` -------------------------------- ### Custom Test Execution Wrapper with utestWrap Source: https://context7.com/com-lihaoyi/utest/llms.txt Override `utestWrap(path, runBody)` to gain full control over test execution, enabling features like logging, custom retries, dependency injection, or resource lifecycle management around every test. The `runBody` parameter is a `Future` representing the test's execution. ```scala import utest._ import scala.concurrent.{ExecutionContext, Future} class WrappedTestDemo extends TestSuite { override def utestWrap(path: Seq[String], runBody: => Future[Any]) (implicit ec: ExecutionContext): Future[Any] = { val label = path.mkString(".") println(s"[START] $label") val t0 = System.currentTimeMillis() runBody.andThen { case result => val elapsed = System.currentTimeMillis() - t0 println(s"[END] $label (${elapsed}ms) => $result") } } val tests = Tests { test("wrapped test") { Thread.sleep(10) 42 } } } // Output: // [START] wrapped test // [END] wrapped test (10ms) => Success(42) ``` -------------------------------- ### Using assertGoldenLiteral in Helper Methods Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Demonstrates how to use `assertGoldenLiteral` in a helper method. The helper method should accept the golden literal as `utest.framework.GoldenFix.Span[T]` to capture source metadata and an implicit `utest.framework.GoldenFix.Reporter`. ```scala def goldenHelper(value: List[Int], golden: utest.framework.GoldenFix.Span[List[Int]]) = { assertGoldenLiteral(value, golden) } test "test"{ val x = List(1, 2) goldenHelper(x, List(1, 2)) } ``` -------------------------------- ### Asynchronous Tests with Future Source: https://context7.com/com-lihaoyi/utest/llms.txt Tests returning a `Future[T]` are treated as asynchronous, with uTest waiting for the `Future` to complete before recording the result. Use `.runAsync` for non-blocking execution. Asynchronous tests within the same suite execute sequentially by default. ```scala import utest._ import scala.concurrent.{Future, ExecutionContext} class AsyncTestDemo extends TestSuite { implicit val ec: ExecutionContext = ExecutionContext.global val tests = Tests { test("async success") { Future { Thread.sleep(50) assert(1 + 1 == 2) "done" } } test("async failure") { Future { assert(false) // AssertionError propagated through the Future } } test("sequential ordering") { // Future tests in the same suite run sequentially by default Future { 42 } } } } ``` -------------------------------- ### Implement Local Retries for Flaky Tests Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Wrap individual tests or expressions in a `retry` block to automatically retry them a specified number of times before failing. This is useful for mitigating intermittent test failures. ```scala object LocalRetryTests extends utest.TestSuite{ val flaky = new FlakyThing def tests = Tests{ test("hello") - retry(3){ flaky.run } } } ``` -------------------------------- ### Write Golden Literal Tests with assertGoldenLiteral Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Use assertGoldenLiteral to automatically fill in expected values. Pass () as the current literal and run with UTEST_UPDATE_GOLDEN_TESTS=1 to update the code. Only supported on Scala-JVM. ```scala val x = List(1, 2) assertGoldenLiteral(x, ()) ``` ```scala val x = List(1, 2) assertGoldenLiteral(x, List(1, 2)) ``` -------------------------------- ### Smart Boolean Assertion with utest Source: https://context7.com/com-lihaoyi/utest/llms.txt Use `assert` to check boolean conditions. It captures local variable names, types, and values, providing a detailed diff on failure. Multiple expressions can be checked in a single call. ```scala import utest._ class AssertDemo extends TestSuite { val tests = Tests { test("smart assert captures locals") { val x = 1 val y = "2" assert(x > 0) // passes assert(x.toString == y) // fails with rich output: // utest.AssertionError: x.toString == y // x: Int = 1 // y: String = "2" // - "1" // + "2" } test("exception inside assert is reported") { val x = 1L val y = 0L assert(x / y == 10) // fails with: // utest.AssertionError: assert(x / y == 10) // caused by: java.lang.ArithmeticException: / by zero // x: Long = 1 // y: Long = 0 } test("multiple expressions") { val a = 1 val b = 2 assert(a > 0, b > 0, a + b == 3) // all checked; first failure is thrown } } } ``` -------------------------------- ### Use TestPath for Dynamic Test Logic Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Utilize the implicit `TestPath` to access the current test's path, allowing dynamic logic based on the test name without explicit parameter passing. ```scala // Also works! val tests = Tests{ def runTestChecks()(implicit path: utest.framework.TestPath) = { val fileName = path.value.last // lots of code using fileName } test("hello"){ runTestChecks() } test("world"){ runTestChecks() } test("i"){ runTestChecks() } test("am"){ runTestChecks() } test("cow"){ runTestChecks() } } ``` -------------------------------- ### Arrow Assert (`==>`) with utest Source: https://context7.com/com-lihaoyi/utest/llms.txt The `==>` operator is syntactic sugar for `assert(a == b)`. It's useful for comparing primitives and arrays by content, offering a more readable syntax. ```scala import utest._ class ArrowAssertDemo extends TestSuite { val tests = Tests { test("arrow asserts") { 1 ==> 1 // passes "hello".length ==> 5 // passes Array(1, 2, 3) ==> Array(1, 2, 3) // passes — arrays compared by content List(1, 2) ==> List(1, 2) // passes try { 1 ==> 2 // throws java.lang.AssertionError: ==> assertion failed: 1 != 2 } catch { case e: AssertionError => e.getMessage } } } } ``` -------------------------------- ### Local Retry Wrapper: retry Source: https://context7.com/com-lihaoyi/utest/llms.txt Wrap individual test expressions in `retry(n){ ... }` to retry up to `n` times before failing. Useful for isolating flaky operations without enabling retries suite-wide. ```scala import utest._ class LocalRetryDemo extends TestSuite { var count = 0 val tests = Tests { test("flaky operation") - retry(3) { count += 1 if (count < 3) throw new Exception(s"Not ready yet (attempt $count)") count // succeeds on 3rd attempt } test("retry block inline") { val result = retry(5) { // some flaky external call 42 } assert(result == 42) } } } ``` -------------------------------- ### Assert Value Matches Pattern with assertMatch Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Use assertMatch to verify if a value conforms to a specific pattern. It supports Scala's pattern matching syntax, including wildcards and guards, providing more flexibility than simple equality checks. Errors include debugging information. ```scala assertMatch(Seq(1, 2, 3)){case Seq(1, 2) =>} // AssertionError: Matching failed Seq(1, 2, 3) ``` -------------------------------- ### Pattern Match Assertion (`assertMatch`) with utest Source: https://context7.com/com-lihaoyi/utest/llms.txt Use `assertMatch(value){ case Pattern => }` to check if a value matches a given pattern. It supports wildcards, guards, and alternatives. ```scala import utest._ class AssertMatchDemo extends TestSuite { val tests = Tests { test("exact match") { assertMatch(Seq(1, 2, 3)) { case Seq(1, 2, 3) => } } test("wildcard match") { assertMatch(Seq(1, 99, 3)) { case Seq(1, _, 3) => } // _ matches any middle element } test("match failure") { try { assertMatch(Seq(1, 2, 3)) { case Seq(1, 2) => } } catch { case e: utest.AssertionError => // AssertionError: Matching failed Seq(1, 2, 3) e.getMessage } } } } ``` -------------------------------- ### Composing Test Suites with Concatenation and Prefixing Source: https://context7.com/com-lihaoyi/utest/llms.txt The `++` operator merges two `Tests` blocks, and `.prefix(name)` nests all tests under a group name. This allows composing test suites from reusable components. ```scala import utest._ val mathTests = Tests { test("add") { assert(1 + 1 == 2) } test("sub") { assert(3 - 1 == 2) } } val stringTests = Tests { test("length") { assert("hi".length == 2) } } class ComposedTests extends TestSuite { val tests = mathTests.prefix("math") ++ stringTests.prefix("strings") } // Tests: math.add, math.sub, strings.length ``` -------------------------------- ### Nesting Tests in uTest Source: https://context7.com/com-lihaoyi/utest/llms.txt Tests can be nested arbitrarily deep. Only the innermost blocks are executed as tests; enclosing blocks provide shared initialization code that runs fresh for every inner test. ```scala import utest._ class NestedTests extends TestSuite { val tests = Tests { val x = 1 // shared initialization, re-evaluated per inner test test("outer1") { val y = x + 1 test("inner1") { assert(x == 1, y == 2) (x, y) // prints "(1,2)" on success } test("inner2") { val z = y + 1 assert(z == 3) } } test("outer2") { test("inner3") { assert(x == 1) } } } } ``` -------------------------------- ### Add uTest Dependency for Mill Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Configure your Mill build file to include the uTest library for Scala-JVM, Scala.js, or Scala-Native projects, and specify the test framework. ```scala def mvnDeps = Seq(mvn"com.lihaoyi::utest:0.10.0-RC1") // Scala-JVM def mvnDeps = Seq(mvn"com.lihaoyi::utest::0.10.0-RC1") // Scala.js or Scala-Native def testFramework = "utest.runner.Framework" ``` -------------------------------- ### Golden Literal Testing in uTest Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Supports golden testing via `assertGoldenLiteral` and `assertGoldenFile`. This helps in filling and updating the 'expected' values for assertions. ```scala assertGoldenLiteral ``` ```scala assertGoldenFile ``` -------------------------------- ### Test Asynchronous Operations with assertEventually/assertContinually Source: https://github.com/com-lihaoyi/utest/blob/master/readme.md Employ `assertEventually` and `assertContinually` for testing asynchronous operations. These macros use a retry-loop mechanism. Default retry interval is 0.1 seconds, up to 1 second. ```scala val x = Seq(12) assertEventually(x == Nil) // utest.AssertionError: assertEventually(x == Nil) // x: Seq[Int] = List(12) ``` ```scala implicit val retryMax = RetryMax(300.millis) implicit val retryInterval = RetryInterval(50.millis) ```