Access ScalaTest test name from inside test?

后端 未结 3 1204
伪装坚强ぢ
伪装坚强ぢ 2021-02-13 23:30

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 testi

相关标签:
3条回答
  • 2021-02-14 00:01

    Here's a solution. Extend this class instead of FreeSpec. License: CC0.

    Edit: This doesn't work with concurrent tests though.

    (The difference between this approach and the other answer, is that 1) here there's a currentTestName field, and in the other answer the test name is passed to the test body, and 2) this test name includes all test branch names concatenated + the actual test name, whereas the other answer's test name is exactly the test name (without test branch names).)

    (Ooops, you'd need to use getOrElse ... instead of my lovely getOrDie.)

    /**
     * Adds a field `currentTestName` that you can use inside a FreeSpec test,
     * if you for example have many tests that take rather long, and you wonder
     * which one is currently running.
     */
    trait RichFreeSpec extends FreeSpec {
    
      private var _currentTestName: Option[String] = None
      def currentTestName = _currentTestName getOrDie "DwE90RXP2"
    
      protected override def runTest(testName: String, args: org.scalatest.Args) {
        _currentTestName = Some(testName)
        super.runTest(testName, args)
      }
    }
    
    0 讨论(0)
  • 2021-02-14 00:02

    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")
        }
      }
    }
    
    0 讨论(0)
  • 2021-02-14 00:05

    Create your own trait, let say RichFreeSpec.

    trait RichFreeSpec extends Free {
      protected final class RichFreeSpecStringWrapper(name: scala.Predef.String) {
        def in(f: String => scala.Unit) {
          def f2 = f(name)
          new WordSpecStringWrapper(string).in(f2)
        }
      }  
    
      protected implicit def convertToRichFreeSpecStringWrapper(n: scala.Predef.String): = {
        new RichFreeSpecStringWrapper(n)
      }
    }
    

    Than just use:

    "sth" in { testName => 
       ...
     }
    

    Of course, you can go further and implement the full name hierarchy.

    0 讨论(0)
提交回复
热议问题