zio-bdd

A BDD testing framework integrating Gherkin-style tests with ZIO’s effect system

View the Project on GitHub EtaCassiopeia/zio-bdd

Advanced Features in zio-bdd

This page delves into advanced capabilities of zio-bdd, including integrating ZIO services, managing complex state, using ScenarioContext effectively, and leveraging custom reporters. These features enable you to write sophisticated tests for complex applications.

Integrating ZIO Services

zio-bdd seamlessly integrates with ZIO’s dependency injection system via ZLayer. This allows you to provide services to your step definitions, making your tests modular and easy to manage.

Providing Services

In your ZIOSteps subclass, override the environment method to provide the required services:

override def environment: ZLayer[Any, Any, Env] =
  ZLayer.make[Env](
    Service1.live,
    Service2.live
  )

Using Services in Steps

Access services in your step definitions using ZIO.service:

When("some action is performed") {
  for {
    service <- ZIO.service[Service1]
    result  <- service.doSomething()
    // ...
  } yield ()
}

This approach keeps your tests clean and decoupled from service implementations.

Managing Complex State

For tests requiring intricate state management, ScenarioContext can hold complex data structures. Define a case class to represent your state and provide an implicit Schema for serialization.

Example

case class ComplexState(users: Map[String, User], currentUser: Option[String])
implicit val schema: Schema[ComplexState] = DeriveSchema.gen[ComplexState]

Given("a user named " / string) { (name: String) =>
  for {
    state <- ScenarioContext.get
    updatedUsers = state.users + (name -> User(name))
    _ <- ScenarioContext.update(_.copy(users = updatedUsers))
  } yield ()
}

Custom Reporters

While zio-bdd provides built-in reporters, you can create custom reporters for specialized output formats.

Implementing a Custom Reporter

Extend the Reporter trait:

class CustomReporter extends Reporter {
  override def report(results: List[FeatureResult]): ZIO[Any, Nothing, Unit] = {
    // Custom reporting logic
    ZIO.succeed(())
  }
}
@Suite(reporters = Array("custom"))
object MySpec extends ZIOSteps[Env, State] {
  // ...
}

Scenario Outlines and Examples

zio-bdd fully supports Gherkin’s Scenario Outline and Examples for data-driven testing.

Defining Steps for Outlines

Write step definitions as usual, using extractors for placeholders:

Given("a user named " / string) { (name: String) =>
  // ...
}

Background Steps

Gherkin’s Background section runs before each scenario in a feature. Define steps for background as you would for any other step.

Example

In your feature file:

Feature: User Management
  Background:
    Given a system is running
  Scenario: Create user
    When a user is created
    Then the user exists

Define the background step:

Given("a system is running") {
  // Setup system
}

Best Practices

Next Steps