Search code examples
scalaintegration-testingscalatest

Access ScalaTest test name from inside test?


Is it possible to access the name of the currently executing test, from within a ScalaTest test? (And how would I do it?)

Background:

I'm testing that my Data Access Object eventually throws an OverQuotaException if a user e.g. creates too many pages. These tests take rather long to run. To feel happier, I'd like to print the progress to stdout — and since there are quite many tests, I'd like to include the test name in the output, so I know what test is currently being run.

(I didn't find any seemingly relevant function here: http://www.artima.com/docs-scalatest-2.0.M5/#org.scalatest.FreeSpec )

Example:

  "QuotaCharger can" - {
    "charge and decline quota consumers" - {

      "charge a per site IP number (guest user)" in {
         // ... Here, a guest user post very many comments until it's over quota.
         // This takes a little while, and there are many similar tests.

         // ---> Here <--- I'd like to access the string:
         //   "charge a per site IP number (guest user)",
         //  is that possible somehow?
      }

Solution

  • The intended way to do that is to override withFixture and capture the test data. In this use case, it is better to override withFixture in fixture.FreeSpec so you can pass the test data into each test rather than using a var. Info on that is here:

    http://www.artima.com/docs-scalatest-2.0.M5/org/scalatest/FreeSpec.html#withFixtureNoArgTest

    When I saw your question this morning I realized ScalaTest should have a trait that does this, so I just added one. It will be in 2.0.M6, the next milestone release, but in the meantime you can use a local copy. Here it is:

    import org.scalatest._
    
    /**
     * Trait that when mixed into a <code>fixture.Suite</code> passes the
     * <code>TestData</code> passed to <code>withFixture</code> as a fixture into each test.
     *
     * @author Bill Venners
     */
    trait TestDataFixture { this: fixture.Suite =>
    
      /**
       * The type of the fixture, which is <code>TestData</code>.
       */
      type FixtureParam = TestData
    
      /**
       * Invoke the test function, passing to the the test function to itself, because
       * in addition to being the test function, it is the <code>TestData</code> for the test.
       *
       * <p>
       * To enable stacking of traits that define <code>withFixture(NoArgTest)</code>, this method does not
       * invoke the test function directly. Instead, it delegates responsibility for invoking the test function
       * to <code>withFixture(NoArgTest)</code>.
       * </p>
       *
       * @param test the <code>OneArgTest</code> to invoke, passing in the
       *   <code>TestData</code> fixture
       */
      def withFixture(test: OneArgTest) {
        withFixture(test.toNoArgTest(test))
      }
    }
    

    You would use it like this:

    import org.scalatest._
    
    class MySpec extends fixture.FreeSpec with TestDataFixture {
      "this technique" - {
        "should work" in { td =>
          assert(td.name == "this technique should work")
         }
        "should be easy" in { td =>
          assert(td.name == "this technique should be easy")
        }
      }
    }