Search code examples
scalacucumberscalatest

Scenario outline in scalatest


I´m implementing my test framework using scalatest and I think I made a mistake using this framework instead of Cucumber

I´m trying to use some sort of features as Scenario outline of cucumber to avoid break DRY

here my problem

  feature("Features of mus client") {
    scenario("GET message with mus client") {
      Given("a Musin message")
      val config: Properties = new Properties
      config.put("method", "POST")
      config.put("encoding", "UTF-8")
      config.put("uri", "http://localhost:9083/musClient")
      When("I make a request to f2e")
      val response = HttpClientTest.request(config, createJSON(READ))
      Then("The message it´s returned successfully")
      assert(response != null)
    }

    scenario("POST message with mus client") {
      Given("a Musin message")
      val config: Properties = new Properties
      config.put("method", "POST")
      config.put("encoding", "UTF-8")
      config.put("uri", "http://localhost:9083/musClient")
      When("I make a request to f2e")
      val response = HttpClientTest.request(config, createJSON(CREATE))
      Then("The message it´s returned successfully")
      assert(response != null)
    }

As you can see I have two scenarios where the 99% it´s the same steps but a variable that change the request.

Any idea how to do this elegant and efficient in scalatest


Solution

  • And I'm one of those too who chose scalatest over cucumber, cucumber was too much for me(ME) to write the feature file, and then come back to scala/java file and change accordingly. Maintain two files. I actually played cucumber java, scala cucumber might be more fluent. Anyway, I am liking scalatest so far for all my unit testing, component testing and the flow testing.

    In case like yours if the properties are common for multiple scenarios and you won't mutate inside scenarios then defining as common property would be fine, as below.

    class E2E extends FeatureSpec with GivenWhenThen {
      feature("Features of mus client") {
    
        Given("http config")
        val config: Properties = new Properties(){{
            put("method", "POST") //you are doing POST in both case by the way
            put("encoding", "UTF-8")
            put("uri", "http://localhost:9083/musClient")
         }}
    
        scenario("GET message with mus client") {
    
          When("I make a request to f2e")
          val response = HttpClientTest.request(config, createJSON(READ))
    
          Then("The message it´s returned successfully")
          assert(response != null)
        }
    
        scenario("POST message with mus client") {
    
          When("I make a request to f2e")
          val response = HttpClientTest.request(config, createJSON(CREATE))
    
          Then("The message it´s returned successfully")
          assert(response != null)
    
        }
      }
    }
    

    But, You might also want to use property based testing for the only part that changes, property based check was very fluent and readable in spock framework.

    property based check in scalatest would look like below where I am testing for two different input parameters. (you neeed import org.scalatest.prop.TableDrivenPropertyChecks._)

    class TestE2E extends FeatureSpec with GivenWhenThen {
    
      val requestResponse =
        Table(
          ("request", "response"),
          (  "GET",   "GET-something"),
          ( "POST",   "POST-something")
        )
    
      feature("testMe") {
    
        forAll (requestResponse) { (givenRequestFromTable: String, expectedResponseFromTable: String) =>
    
          scenario("for input " + givenRequestFromTable) {
    
            When("input is " + givenRequestFromTable)
            val output = testMe(input = givenRequestFromTable)
    
            Then("responseFromTable has something appended to it")
            assert(output == expectedResponseFromTable)
          }
        }
      }
    
      def testMe(input: String) : String = {
         input + "-something"
      }
    }
    

    There would be two scenarios based on two given properties, two tests

    And for you, the tests would be something as below with property based, hope there's no compile error :)

    import org.scalatest.prop.TableDrivenPropertyChecks._
    import org.scalatest.prop.Tables.Table
    import org.scalatest.{FeatureSpec, GivenWhenThen}
    
    class PaulWritesSpecs extends FeatureSpec with GivenWhenThen {
    
      val requestResponse =
        Table(
          ("httpMethod", "requestType"),
          ("GET", READ),
          ("POST", CREATE))
    
      feature("Features of mus client") {
    
        forAll(requestResponse) { (httpMethod: String, requestType: String) => {
    
            scenario(s"$httpMethod message with mus client") {
    
              Given("http config")
              val config: Properties = new Properties() {{
                put("method", httpMethod)
                put("encoding", "UTF-8")
                put("uri", "http://localhost:9083/musClient")
              }}
    
              When("I make a request to f2e")
              val response = HttpClientTest.request(config, createJSON(requestType))
    
              Then("The message it´s returned successfully")
              assert(response != null)
            }
          }
        }
      }
    }