2017-08-21 10 views
0

私はScalaには新しく、主に一般的にはJVMになっています。 bookで文がありScalaでのテスト

アサーションが失敗したときに詳細なエラーメッセージを提供するために、ScalaTest はそれぞれに渡された式は、コンパイル時に 時間を呼び出しを主張分析します。

私を多く混乱させました。

これは実際にはどういう意味ですか? ScalaTestはどのようにコンパイル時間情報にアクセスできますか?

答えて

2

ScalaTestはこの目的でmacrosを使用します。マクロを使って、assertに渡された式を解析することができます。 ScalaTestはPredef packageに標準のScala assertを使用せず、assertの独自の実装を提供しています。詳細はScalaTest Using assertionsで読むことができます。

+0

だから、それは.NETに似ている[表現](https://msdn.microsoft.com/en-us/library/system.linq .expressions.expression(v = vs.110).aspx)またはF#の[Code Quotations](https:// docs。 –

+0

私はそれらが似ているとは思わない - どちらも実行時に使用される表現の表現を提供するように思われる。マクロも式の表現を受け取りますが、その差はコンパイル時に実行されます(ソースコードのコンパイル時にコンパイラによって)。 – Suma

2

Scalaはこの種の機能を有効にするためにmacrosをサポートしています。 Scalaマクロは、コールサイトの構文ツリーを解析して、そこから有益な情報を抽出することができます。 ScalaTestのようなライブラリは、マクロを使用して、コールサイトに関する情報を取得して、例えば、変数名に基づくエラーメッセージ。

2

は、次のいくつかの例を(私はMatchersGivenWhenThenなどのScalaTestの機能を使用する)考えてみましょう:

まず一つは、オブジェクトの平等のテストについてです。

"ScalaTest" should "provide descriptive error messages when checking objects equality" in{ 
    Given("two different List objects") 
    val list1 = List("I", "am", "the", "list") 
    val list2 = Seq("No", "I", "am", "the", "list") 
    When("we try to check them for equality with ScalaTest tools") 
    Then("we can see what exactly differs") 
    list1 should equal(list2) 
    } 

値の宣言でオブジェクトの種類が異なることに注意してください。 実行すると、出力にList("I", "am", "the", "list") did not equal List("No", "I", "am", "the", "list")が表示されます。 ScalaTestは柔軟性があり、2つのリストが異なり、エラーメッセージに表示されることを伝えることができます。 40 was not greater than 50

"ScalaTest" should "provide descriptive error messages when comparing values with natural ordering" in{ 
    Given("two different numbers") 
    val value1 = 40l 
    val value2 = 50l 
    When("we try to compare them for equality with ScalaTest tools") 
    Then("we ScalaTest failure message should clearly state what happened") 
    value1 should be > value2 
    } 

は、この出力を取得することを実行する:

次の例では、比較値を示しています。 これは、そのようなテストのためにできるだけ説明的です。 ご覧のとおり、value1 should be > value2アサーションはうまく解析され、40 was not greater than 50エラーメッセージが表示されます。

今度はPredef.scalaから標準assert方法を考えてみましょう:

"Predef.assert()" should "not provide descriptive enough error messages" in{ 
    Given("two different List objects") 
    val list1 = List("I", "am", "the", "list") 
    val list2 = Seq("No", "I", "am", "the", "list") 
    When("we try to check them for equality with Predef.scala asserts") 
    Then("we only get an exception with compile-time provided message") 
    Predef.assert(list1 == list2, "Lists are not equal") 
    succeed 
    } 

それはassertion failed: Lists are not equalを出力します。これは、ScalaTestを使用する場合よりも記述性が劣ります。

上記の回答で既に述べたように、このような動作を実装するためにマクロが使用されています。 Assertions.scalaでScalaTest assertメソッドの宣言は以下の通りです:

def assert(condition: Boolean)(implicit prettifier: Prettifier, pos: source.Position): Assertion = macro AssertionsMacro.assert

関連する問題