or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

advanced.mdassertions.mdasync.mdfixtures.mdindex.mdmatchers.mdtest-styles.md
tile.json

test-styles.mddocs/

Test Suite Styles

ScalaTest provides multiple testing styles to accommodate different testing preferences, team cultures, and domain-specific languages. Each style offers a different DSL for organizing and writing tests while sharing the same underlying execution engine and assertion capabilities.

Capabilities

FunSuite - Function-Based Testing

xUnit-style testing with named test functions. Ideal for unit testing and teams familiar with JUnit/TestNG.

/**
 * Function-based test suite similar to xUnit frameworks
 */
abstract class AnyFunSuite extends Suite with TestSuite with Informing with Notifying with Alerting with Documenting {
  /**
   * Register a test with the given name and function
   * @param testName the name of the test
   * @param testFun the test function to execute
   */
  protected def test(testName: String)(testFun: => Any): Unit
  
  /**
   * Register a test to be ignored
   * @param testName the name of the ignored test  
   * @param testFun the test function (will not be executed)
   */
  protected def ignore(testName: String)(testFun: => Any): Unit
}

/**
 * Asynchronous version returning Future[Assertion]
 */
abstract class AsyncFunSuite extends AsyncTestSuite with TestSuite {
  protected def test(testName: String)(testFun: => Future[compatible.Assertion]): Unit
  protected def ignore(testName: String)(testFun: => Future[compatible.Assertion]): Unit
}

Usage Example:

import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers

class MathUtilsSpec extends AnyFunSuite with Matchers {
  
  test("addition should work correctly") {
    val result = MathUtils.add(2, 3)
    result should equal(5)
  }
  
  test("division by zero should throw exception") {
    assertThrows[ArithmeticException] {
      MathUtils.divide(10, 0)
    }
  }
  
  ignore("complex calculation - not implemented yet") {
    // Test will be ignored
    pending
  }
}

FlatSpec - Flat Specification Style

Flat, linear test style that encourages descriptive test names. Good for behavior-driven development and readable test reports.

/**
 * Flat specification style with subject-behavior syntax
 */
abstract class AnyFlatSpec extends Suite with TestSuite {
  /**
   * Define behavior for a subject using "should", "must", "can"
   * Usage: "Subject" should "behavior description" in { test }
   */
  protected def behavior(description: String): Unit
  
  /**
   * Define ignored behavior
   * Usage: "Subject" should "behavior" ignore { test }
   */
  protected def ignore: Unit
}

abstract class AsyncFlatSpec extends AsyncTestSuite with TestSuite {
  protected def behavior(description: String): Unit
}

Usage Example:

import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class StringUtilsSpec extends AnyFlatSpec with Matchers {
  
  behavior of "StringUtils"
  
  it should "reverse strings correctly" in {
    StringUtils.reverse("hello") should equal("olleh")
    StringUtils.reverse("") should equal("")
  }
  
  it should "capitalize first letter" in {
    StringUtils.capitalize("hello") should equal("Hello")
    StringUtils.capitalize("HELLO") should equal("HELLO")
  }
  
  "The reverse method" should "handle null input gracefully" in {
    StringUtils.reverse(null) should be(null)
  }
  
  it should "work with unicode characters" ignore {
    // Test not implemented yet
    pending
  }
}

WordSpec - Word-Based Specification

Specification style using nested contexts with "when", "should", "must", and "can". Excellent for complex behavior specification and acceptance testing.

/**
 * Word-based specification style with nested contexts
 */
abstract class AnyWordSpec extends Suite with TestSuite {
  /**
   * Create nested specification contexts
   * Usage: "Subject" when { "condition" should { "behavior" in { test } } }
   */
  protected def when: WordSpecStringWrapper
  protected def should: WordSpecStringWrapper  
  protected def must: WordSpecStringWrapper
  protected def can: WordSpecStringWrapper
  protected def which: WordSpecStringWrapper
}

abstract class AsyncWordSpec extends AsyncTestSuite with TestSuite

Usage Example:

import org.scalatest.wordspec.AnyWordSpec
import org.scalatest.matchers.should.Matchers

class BankAccountSpec extends AnyWordSpec with Matchers {
  
  "A BankAccount" when {
    "newly created" should {
      "have zero balance" in {
        val account = new BankAccount()
        account.balance should equal(0.0)
      }
      
      "accept positive deposits" in {
        val account = new BankAccount()
        account.deposit(100.0)
        account.balance should equal(100.0)
      }
    }
    
    "with sufficient funds" should {
      "allow withdrawals" in {
        val account = new BankAccount()
        account.deposit(100.0)
        account.withdraw(50.0)
        account.balance should equal(50.0)
      }
    }
    
    "with insufficient funds" must {
      "reject withdrawals" in {
        val account = new BankAccount()
        account.deposit(50.0)
        assertThrows[InsufficientFundsException] {
          account.withdraw(100.0)
        }
      }
    }
  }
}

FreeSpec - Free-Form Specification

Free-form specification style with flexible nesting using dashes. Allows natural language test descriptions with arbitrary nesting levels.

/**
 * Free-form specification style with dash-based nesting
 */
abstract class AnyFreeSpec extends Suite with TestSuite {
  /**
   * Create free-form nested specifications
   * Usage: "description" - { test or nested specs }
   */
  protected def -(text: String): FreeSpecStringWrapper
  
  /**
   * Ignore a specification
   * Usage: "description" ignore { test }
   */
  protected def ignore: Unit
}

abstract class AsyncFreeSpec extends AsyncTestSuite with TestSuite

Usage Example:

import org.scalatest.freespec.AnyFreeSpec
import org.scalatest.matchers.should.Matchers

class UserServiceSpec extends AnyFreeSpec with Matchers {
  
  "UserService" - {
    "when creating a new user" - {
      "should validate email format" in {
        val service = new UserService()
        assertThrows[InvalidEmailException] {
          service.createUser("john", "invalid-email")
        }
      }
      
      "should generate unique ID" in {
        val service = new UserService()
        val user1 = service.createUser("john", "john@example.com")
        val user2 = service.createUser("jane", "jane@example.com")
        user1.id should not equal user2.id
      }
      
      "with duplicate email" - {
        "should throw exception" in {
          val service = new UserService()
          service.createUser("john", "john@example.com")
          assertThrows[DuplicateEmailException] {
            service.createUser("jane", "john@example.com")
          }
        }
      }
    }
    
    "when retrieving users" - {
      "should return empty list initially" ignore {
        // Test not implemented
        pending
      }
    }
  }
}

FunSpec - Function Specification Style

RSpec-like specification style with "describe" and "it" blocks. Popular for behavior-driven development with natural language descriptions.

/**
 * Function specification style similar to RSpec
 */
abstract class AnyFunSpec extends Suite with TestSuite {
  /**
   * Describe a component or behavior
   * @param description what is being described
   * @param fun nested specifications or tests
   */
  protected def describe(description: String)(fun: => Unit): Unit
  
  /**
   * Specify individual behavior
   * @param specText behavior description  
   * @param fun test implementation
   */
  protected def it(specText: String)(fun: => Any): Unit
  
  /**
   * Ignore a specification
   */
  protected def ignore(specText: String)(fun: => Any): Unit
}

abstract class AsyncFunSpec extends AsyncTestSuite with TestSuite {
  protected def describe(description: String)(fun: => Unit): Unit
  protected def it(specText: String)(fun: => Future[compatible.Assertion]): Unit
}

Usage Example:

import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.should.Matchers

class CalculatorSpec extends AnyFunSpec with Matchers {
  
  describe("Calculator") {
    describe("when performing addition") {
      it("should add positive numbers correctly") {
        val calc = new Calculator()
        calc.add(2, 3) should equal(5)
      }
      
      it("should handle negative numbers") {
        val calc = new Calculator()
        calc.add(-2, 3) should equal(1)
        calc.add(-2, -3) should equal(-5)
      }
    }
    
    describe("when performing division") {
      it("should divide numbers correctly") {
        val calc = new Calculator()
        calc.divide(10, 2) should equal(5.0)
      }
      
      it("should handle division by zero") {
        val calc = new Calculator()
        assertThrows[ArithmeticException] {
          calc.divide(10, 0)
        }
      }
      
      ignore("should handle floating point precision") {
        // Complex floating point test - not implemented yet
        pending
      }
    }
  }
}

FeatureSpec - Feature Specification Style

Gherkin-inspired BDD style with "Feature" and "Scenario" keywords. Ideal for acceptance testing and stakeholder communication.

/**
 * Feature-driven specification style inspired by Gherkin/Cucumber
 */
abstract class AnyFeatureSpec extends Suite with TestSuite {
  /**
   * Define a feature
   * @param description feature description
   * @param fun scenarios for this feature
   */
  protected def Feature(description: String)(fun: => Unit): Unit
  
  /**
   * Define a scenario within a feature
   * @param description scenario description
   * @param fun test implementation  
   */
  protected def Scenario(description: String)(fun: => Any): Unit
  
  /**
   * Ignore a scenario
   */
  protected def ignore(description: String)(fun: => Any): Unit
}

abstract class AsyncFeatureSpec extends AsyncTestSuite with TestSuite {
  protected def Feature(description: String)(fun: => Unit): Unit
  protected def Scenario(description: String)(fun: => Future[compatible.Assertion]): Unit
}

Usage Example:

import org.scalatest.featurespec.AnyFeatureSpec
import org.scalatest.matchers.should.Matchers
import org.scalatest.GivenWhenThen

class ShoppingCartSpec extends AnyFeatureSpec with Matchers with GivenWhenThen {
  
  Feature("Shopping Cart Management") {
    
    Scenario("Adding items to empty cart") {
      Given("an empty shopping cart")
      val cart = new ShoppingCart()
      cart.items should be empty
      
      When("I add an item")
      val item = Item("Book", 29.99)
      cart.addItem(item)
      
      Then("the cart should contain the item")
      cart.items should contain(item)
      cart.total should equal(29.99)
    }
    
    Scenario("Removing items from cart") {
      Given("a cart with items")
      val cart = new ShoppingCart()
      val book = Item("Book", 29.99)
      val pen = Item("Pen", 2.50)
      cart.addItem(book)
      cart.addItem(pen)
      
      When("I remove an item")
      cart.removeItem(book)
      
      Then("the cart should not contain that item")
      cart.items should not contain book
      cart.items should contain(pen)
      cart.total should equal(2.50)
    }
    
    ignore("Applying discount codes") {
      // Feature not yet implemented
      pending
    }
  }
}

PropSpec - Property-Based Testing Style

Property-based testing style for defining properties that should hold for ranges of data. Integrates well with property testing libraries.

/**
 * Property-based testing specification style
 */
abstract class AnyPropSpec extends Suite with TestSuite {
  /**
   * Define a property that should hold
   * @param testName property description
   * @param fun property test implementation
   */
  protected def property(testName: String)(fun: => Any): Unit
  
  /**
   * Ignore a property
   */
  protected def ignore(testName: String)(fun: => Any): Unit
}

abstract class AsyncPropSpec extends AsyncTestSuite with TestSuite {
  protected def property(testName: String)(fun: => Future[compatible.Assertion]): Unit
}

Usage Example:

import org.scalatest.propspec.AnyPropSpec
import org.scalatest.matchers.should.Matchers

class StringPropertiesSpec extends AnyPropSpec with Matchers {
  
  property("string reverse is idempotent") {
    forAll { (s: String) =>
      StringUtils.reverse(StringUtils.reverse(s)) should equal(s)
    }
  }
  
  property("string length is preserved by reverse") {
    forAll { (s: String) =>
      StringUtils.reverse(s).length should equal(s.length)
    }
  }
  
  property("concatenation length is sum of individual lengths") {
    forAll { (s1: String, s2: String) =>
      (s1 + s2).length should equal(s1.length + s2.length)
    }
  }
  
  ignore("complex unicode normalization properties") {
    // Complex unicode property tests - not implemented
    pending
  }
}

Fixture Support

All test styles support fixture variants for managing test setup and teardown:

Fixture Variants

// Fixture variants available for all styles
abstract class FixtureAnyFunSuite extends fixture.TestSuite
abstract class FixtureAnyFlatSpec extends fixture.TestSuite  
abstract class FixtureAnyWordSpec extends fixture.TestSuite
abstract class FixtureAnyFreeSpec extends fixture.TestSuite
abstract class FixtureAnyFunSpec extends fixture.TestSuite
abstract class FixtureAnyFeatureSpec extends fixture.TestSuite
abstract class FixtureAnyPropSpec extends fixture.TestSuite

// Async fixture variants
abstract class FixtureAsyncFunSuite extends fixture.AsyncTestSuite
abstract class FixtureAsyncFlatSpec extends fixture.AsyncTestSuite
// ... similar pattern for all async variants

Choosing a Test Style

FunSuite: Best for unit testing, simple test cases, teams familiar with xUnit frameworks
FlatSpec: Good for behavior specification, flat test structure, readable reports
WordSpec: Ideal for complex behavior specification, nested contexts, acceptance testing
FreeSpec: Perfect for natural language descriptions, flexible organization, documentation-like tests
FunSpec: Great for BDD, hierarchical organization, teams familiar with RSpec
FeatureSpec: Excellent for acceptance testing, stakeholder communication, Gherkin-style scenarios
PropSpec: Essential for property-based testing, mathematical properties, comprehensive test coverage

All styles can be mixed within the same test suite using Suites wrapper and support the same assertion and matcher capabilities.