Programming in Sala 책으로 스칼라 스터디하면서 정리했던 내용이다. 지금은 3판 번역본도 나왔지만, 약간 앞서서 스터디를 시작해서 2판으로 진행했다.

14장

단언문

  • assert 메소드
  • 조건 충족되지 않으면 AssertionError 발생
def above(that: Elemment): Element = {
  val this1 = this widen that.width
  val that1 = that widen this.width
  assert(this1.width == that1.width)    // assert
  elem(this1.contents ++ that1.contents)
}
  • assert(c, e) : c를 만족하지 않으면, 설명 e(e.toString)를 포함하는 AssertionError 발생
  • ensuring : 어떠한 결과 타입이든 적용 가능
private def widen(w: Int): Element =
  if (w <= width)
    this
  else {
    val left = elem(' ', (w - width) / 2, height)
    val right = elem(' ', w - width - left.width, hegith)
    left beside this beside right
  } ensuring (w <= _.width)         // ensuring. false면 AssertionError
  • 단언문 동작 끄기 : JVM -ea, -da 옵션(동작X), scalac -Xdisable-assertions

단위 테스트

ScalaTest

  • Suite
import org.scalatest.Suite
import Element.elem

class ElementSuite extends Suite {  // Suite 확장
  def testUniformElement() {        // test로 시작하는 메소드
    val ele = elem('x', 2, 3)
    assert(ele.width == 2)
  }
}

// (new ElementSuite).execute() // 실행
  • FunSuite
import org.scalatest.FunSuite
import Element.elem

class ElementSuite extends FunSuite {   // FunSuite 확장
  test("elem result should have passed width") {
    val ele = elem('x', 2, 3)
    assert(ele.width == 2)
  }
}
  • === 연산자 : 비교 실패시 더 많은 메시지 표시
assert(ele.width === 2)
  • expect 메소드 : 예상치를 강조 표시
expect(2) {
  ele.width
}
  • intercept 메소드 : 예외 예상
intercept[IllegalArgumentException] {
  elem('x', -2, 3)
}

JUnit

  • TestCase 확장하여 동일하게 사용 가능
import junit.framework.TestCase
import junit.framework.Assert.assertEquals
import junit.framework.Assert.fail
import Element.elem

class ElementTestCase extends TestCase {
  def testUniformElement() {
    val ele = elem('x', 2, 3)
    assertEquals(2, ele.width)
    assertEquals(3, ele.height)
    try {
      elem('x', -2, 3)  // IllegalArgumentException 이 발생한다고 가정
      fail()
    }
    catch {
      case e: IllegalArgumentException => // 발생하리라 예상
    }
  }
}
  • JUnit3Suite : ScalaTest의 단언 문법 사용
import org.scalatest.junit.JUnit3Suite
import Element.elem

class ElementSuite extends Junit3Suite {
  def testUniformElement() {
    val ele = elem('x', 2, 3)
    assert(ele.width === 2)
    expect(3) { ele.height }
    intercept[IllegalArgumentException] {
      elem('x', -2, 3)
    }
  }
}

TestNG

  • TestNG 실행 장치로 실행 가능
import org.testing.annotations.Test
import org.testing.Assert.assertEquals
import Element.elem

class ElementTests {
  @Test def verifyUniformElement() {
    val ele = elem('x', 2, 3)
    assertEquals(ele.width, 2)
    assertEquals(ele.height, 3)
  }
  @Test(
    expectedExceptions =
      Array(classOf[IllegalArgumentException])
  )
  def elemShouldThrowIAE() { elem('x', -2, 3) }
}
  • TestNGSuite : ScalaTest의 단언 문법 사용
import org.scalatest.testing.TEstNGSuite
import org.testing.annotations.Test
import Element.elem

class ElementSuite extends TestNGSuite {
  @Test def verifyUniformElement() {
    val ele = elem('x', 2, 3)
    assert(ele.width === 2)
    expect(3) { ele.height }
    intercept[IllegalArgumentException] {
      elem('x', -2, 3)
    }
  }
}

BDD 스타일

  • Spec, WordSpec, FlatSpec, FeatureSpec 등 제공
  • FlatSpec 예
import org.scalatest.FlatSpec
import org.scalatest.matchers.ShouldMatchers
import Element.elem

class ElementSpec extends FlatSpec with ShouldMatchers {
  "A UniformElement" should                         // 주제
    "Have a width equal to the passwd value" in {   // 동작 설명문
      val ele = elem('x', 2, 3)
      ele.width should be (2)
    }

  it should "have a height equal to the passed value" in {  // it : 직전 주제 언급
    val ele = elem('x', 2, 3)
    ele.height should be (3)
  }

  it should "throw an IAE if passed a negative width" in {
    evaluating {
      elem('x', -2, 3)
    } should produce [IllegalArgumentException]
  }
}
  • specs 프레임 워크 사용 가능(specs2로 대치됨)

ScalaCheck - 프로퍼티 기반 테스트

import org.scalatest.WordSpec
import org.scalatest.prop.Checkers
import org.scalatest.Prop._
import Element.elem

class ElementSpec extends WordSpec with Checkers {
  "elem result" must {
    "have passed width" in {
      check((w: Int) => w > 0 ==> (elem('x', w, 3).width == w)) // ==> 함의 연산자 : 왼쪽 표현식이 true 이면 오른쪽도 true
    }
    "have passed height" in {
      check((h: Int) => h > 0 ==> (elem('x', 2, h).height == h))
    }
  }
}

테스트 조직

  • Suite 안에 Suite를 포함시켜서 전체를 조직
  • 포함시킬 Suite를 수동 처리
    • nestedSuites 메소드 오버라이드
    • 포함시킬 Suite를 SuperSuite 클래스의 생성자에 전달


+ Recent posts