복붙노트

[SCALA] 주장을 테스트하는 것은 무엇인가 컴파일되지해야

SCALA

주장을 테스트하는 것은 무엇인가 컴파일되지해야

나는 도서관과 일하고 있어요 때 지원 형 레벨의 프로그래밍은, 나는 종종 자신이 (이상한 루프 2012 년 폴 Snively 제시 한 예에서) 다음과 같은 의견을 작성 찾을 수 있음 :

// But these invalid sequences don't compile:
// isValid(_3 :: _1 :: _5 :: _8 :: _8 :: _2 :: _8 :: _6 :: _5 :: HNil)
// isValid(_3 :: _4 :: _5 :: _8 :: _8 :: _2 :: _8 :: _6 :: HNil)

또는이는 볼품 저장소의 예에서 :

/**
 * If we wanted to confirm that the list uniquely contains `Foo` or any
 * subtype of `Foo`, we could first use `unifySubtypes` to upcast any
 * subtypes of `Foo` in the list to `Foo`.
 *
 * The following would not compile, for example:
 */
 //stuff.unifySubtypes[Foo].unique[Foo]

이것은 이러한 메소드의 동작에 대한 몇 가지 사실을 나타내는 매우 거친 방법이며, 우리는 더 공식적인-에 대한 단위 또는 회귀 테스트 등 이러한 주장을하고 싶은 상상할 수

내가 쓴이 볼품 같은 라이브러리의 맥락에서 유용 할 수 있습니다 이유의 구체적인 예를주고, 몇 일 전이 질문에 대한 답변에서 빠른 첫 번째 시도로 다음과 같은 :

import shapeless._

implicit class Uniqueable[L <: HList](l: L) {
  def unique[A](implicit ev: FilterAux[L, A, A :: HNil]) = ev(l).head
}

어디 의도는이 컴파일 것입니다 :

('a' :: 'b :: HNil).unique[Char]

동안이되지 않습니다

('a' :: 'b' :: HNil).unique[Char]

볼품 즐겁게 후자의 경우에 FilterAux 인스턴스를 찾을 때문에 나는, HList에 대해 고유 한 유형 수준의이 구현하지 작업 한 것을 발견 놀랐습니다. 당신은 아마 그것을하지 기대에도 불구하고 즉, 다음은 컴파일 것입니다 :

implicitly[FilterAux[Char :: Char :: HNil, Char, Char :: HNil]]

이 경우, 제가보고되었다 버그 또는 뭔가 버그 틱 - 그리고 그것은 이후에 수정 된 적어도이었다.

더 일반적으로, 우리는 함께 시험-으로 이상이이 같은 유형 수준의 코드를 테스트에 대해 이야기하는 소리가 수 있으므로 FilterAux는 단위 같은 작업 방법에 대한 나의 기대에 암시했다 불변의 종류를 확인하고자 상상할 수 시험 대 유형의 상대적 장점에 대한 모든 최근의 논쟁.

문제는 내가 뭔가 컴파일하지 않아야 주장 프로그래머를 할 수 있습니다 (모든 플랫폼) 프레임 워크를 테스트 어떤 종류의 모르겠입니다.

FilterAux의 경우 이전 암시 인수-와 null이 기본 트릭을 사용하는 것입니다 내가 상상할 수있는 한 가지 방법 :

def assertNoInstanceOf[T](implicit instance: T = null) = assert(instance == null)

당신이 당신의 단위 테스트에 다음을 쓸 수 것이다 :

assertNoInstanceOf[FilterAux[Char :: Char :: HNil, Char, Char :: HNil]]

다음은하지만,보다 편리하고 표현을 많이의 지옥이 될 것입니다 :

assertDoesntCompile(('a' :: 'b' :: HNil).unique[Char])

나는 이것을 원한다. 내 질문은 사람이-이상적으로 그것을 스칼라에 대한 같은 원격 아무것도를 지원하는 테스트 라이브러리 또는 프레임 워크를 알고 있는지,하지만 난 아무것도 해결됩니다.

해결법

  1. ==============================

    1.아니 프레임 워크, 그러나 호르헤 오티즈 (@JorgeO)는 지원이 아닌 컴파일 테스트를 2012 년 그는 NEScala에서 정사각형의 악성 라이브러리에 대한 테스트에 추가 된 몇 가지 유틸리티를 언급 : 당신이 여기에서 예를 찾을 수 있습니다. 나는 아주 잠시 동안 볼품이 같은 것을 추가하는 것을 의미했습니다.

    아니 프레임 워크, 그러나 호르헤 오티즈 (@JorgeO)는 지원이 아닌 컴파일 테스트를 2012 년 그는 NEScala에서 정사각형의 악성 라이브러리에 대한 테스트에 추가 된 몇 가지 유틸리티를 언급 : 당신이 여기에서 예를 찾을 수 있습니다. 나는 아주 잠시 동안 볼품이 같은 것을 추가하는 것을 의미했습니다.

    최근 롤랜드 쿤 (@rolandkuhn가) 채널을 입력 Akka에 대한 시험을, 유사한 메커니즘, 스칼라 2.10의 런타임 컴파일을 사용하여이 시간을 추가했다.

    이들은 물론 모두 동적 시험이다 : 그들은 (테스트) 런타임에 컴파일하지 않습니다해야하는 경우 뭔가를 실패합니다. 예 : 형식화되지 않은 매크로는 정적 옵션을 제공 할 수 있습니다. 매크로)는 유형이 지정되지 않은 나무를 받아 그것을 확인 입력이 성공하면 유형의 오류가 발생 할 수 있습니다. 이 볼품의 매크로 낙원 지점에 실험 뭔가 수 있습니다. 하지만 분명히 2.10.0 또는 이전 버전을위한 솔루션.

    최신 정보

    때문에 스테판 Zeiger (@StefanZeiger)에, 질문, 다른 접근 방식을 응답하기 때문에 부상하고있다. 이 사람은, 그러나 그것은 또한 스칼라 2.10.x.와 호환 흥미로운 때문에, 위에서 언급 유형이 지정되지 않은 매크로처럼, 그것은 (테스트) 런타임 검사보다는 컴파일 시간입니다 따라서 나는 롤랜드의 접근 방식에 바람직하다 생각합니다.

    나는 지금이 지정되지 않은 매크로 접근 방식을 사용 스테판의 접근 방식을 사용하여 2.10.x과 매크로 낙원, 호르헤의 접근 방식을 사용하여 2.9.x에 대한 볼품에 구현을 추가했습니다. 해당 시험의 예로는 2.10.x 위해 여기 매크로 파라다이스 여기, 2.9.x 여기를 찾을 수있다.

    형식화되지 않은 매크로 테스트는 깨끗한하지만 스테판의 2.10.x 호환 접근 방식은 가까운 초입니다.

  2. ==============================

    2.2.1.0 ScalaTest는 명제에 대해 다음 구문이 있습니다 :

    2.1.0 ScalaTest는 명제에 대해 다음 구문이 있습니다 :

    assertTypeError("val s: String = 1")
    

    그리고 매처 (Matchers)에 대한 :

    "val s: String = 1" shouldNot compile
    
  3. ==============================

    3.당신은 스칼라 프로젝트 partest에 대해 알고 있습니까? 예를 들면 CompilerTest는 다음과 같은 문서가 있습니다 :

    당신은 스칼라 프로젝트 partest에 대해 알고 있습니까? 예를 들면 CompilerTest는 다음과 같은 문서가 있습니다 :

    /** For testing compiler internals directly.
    * Each source code string in "sources" will be compiled, and
    * the check function will be called with the source code and the
    * resulting CompilationUnit. The check implementation should
    * test for what it wants to test and fail (via assert or other
    * exception) if it is not happy.
    */
    

    이 소스 https://github.com/scala/scala/blob/master/test/files/neg/divergent-implicit.scala이 결과 https://github.com/scala을해야합니다 여부를 예를 들어 확인 할 수있다 /scala/blob/master/test/files/neg/divergent-implicit.check

    그것은 (당신이 주장의 관점에서 테스트 케이스를 지정하지 않기 때문에) 귀하의 질문에 매우 적합 아니지만 접근 할 수 및 / 또는 당신에게 기선을 줄 수 있습니다.

  4. ==============================

    4.마일 사빈 I에서 제공하는 링크를 기반으로는 akka 버전을 사용 할 수 있었다

    마일 사빈 I에서 제공하는 링크를 기반으로는 akka 버전을 사용 할 수 있었다

    import scala.tools.reflect.ToolBox
    
    object TestUtils {
    
      def eval(code: String, compileOptions: String = "-cp target/classes"): Any = {
        val tb = mkToolbox(compileOptions)
        tb.eval(tb.parse(code))
      }
    
      def mkToolbox(compileOptions: String = ""): ToolBox[_ <: scala.reflect.api.Universe] = {
        val m = scala.reflect.runtime.currentMirror
        m.mkToolBox(options = compileOptions)
      }
    }
    

    그럼 내 테스트에서 나는이처럼 사용

    def result = TestUtils.eval(
      """|import ee.ui.events.Event
         |import ee.ui.events.ReadOnlyEvent
         |     
         |val myObj = new {
         |  private val writableEvent = Event[Int]
         |  val event:ReadOnlyEvent[Int] = writableEvent
         |}
         |
         |// will not compile:
         |myObj.event.fire
         |""".stripMargin)
    
    result must throwA[ToolBoxError].like {
      case e => 
        e.getMessage must contain("value fire is not a member of ee.ui.events.ReadOnlyEvent[Int]") 
    }
    
  5. ==============================

    5.μTest의 compileError 매크로 그냥 않습니다 :

    μTest의 compileError 매크로 그냥 않습니다 :

    compileError("true * false")
    // CompileError.Type("value * is not a member of Boolean")
    
    compileError("(}")
    // CompileError.Parse("')' expected but '}' found.")
    
  6. from https://stackoverflow.com/questions/15125457/testing-an-assertion-that-something-must-not-compile by cc-by-sa and MIT license