[Scala] 단언문과 테스트

smlee·2023년 8월 17일
0

Scala

목록 보기
19/37
post-thumbnail

이 글은 Programming in Scala 4/e Chapter14를 읽고 작성한 글입니다.


단언문과 테스트는 작성한 소프트웨어가 제대로 동작하는 지 확인하는 방법이다.

단언문 (assert)

스칼라는 assert 메서드를 호출하는 방식으로 단언문을 작성한다. 단언문은 조건을 만족하지 않는 경우 AssertionError를 발생시킨다.

assert(조건, 설명)

위의 메서드는 조건을 만족하지 않는 경우 설명을 포함하는 AssertionError를 발생시킨다.
assert 메서드는 AssertionError 객체 안에 있는 toString 메서드를 호출한다.

def above(that:Element):Element = {
	val this1 = this widen that.width
    val that1 = that widen this.width
    
    assert(this1.width == that1.width)
    elem(this.contents ++ that1.contents)
}

위는 2개의 값이 같은지를 확인 후, 다르다면 에러를 띄우는 코드이다. 만약 위의 코드를 간결하게 하고 싶다면 Predef에 있는 ensuring이라는 도우미 메서드를 사용해 작성할 수 있다.

private def widen(w: Int):Element = 
	if(w <= width) this
    else {
    	val left = elem(' ', (w - width) / 2, height)
        var right = elem(' ', w - width - left.width, height)
        left beside this beside right
    } ensuring (w <= _.width)

ensuring 메서드는 암시적 변환을 사용하므로 어떠한 결과 타입이든 적용할 수 있다.


JVM에 -ea-da 명령행 옵션을 사용하면 확인의 동작을 켜거나 끌 수 있다.
작동 시, 각 단언문은 소프트웨어가 실행되면서 접하는 실제 데이터를 사용하는 작은 테스트 역할을 한다.
그렇다면 외부 단위 테스트는 어떻게 작성할까? 단위 테스트는 스스로 데이터를 제공하며, 애플리케이션과 독립적으로 실행할 수 있다.

스칼라에서 테스트하기

테스트 도구는 매우 다양하다. Java 기반이므로 유명한 자바 테스트 도구인 J Unit을 사용할 수 있고, TestNg를 사용할 수 있다. 그리고, 스칼라로 만들어진 ScalaTest나 specs2, ScalaCheck 등이 있다.
이 중에서 ScalaTest는 가장 유연한 스칼라 테스트 프레임워크로, 다른 문제를 풀기 위해 쉽게 커스터마이즈할 수 있다.

import org.scalatest.funsuite.AnyFunSuite
import Element.elem

class ElementSuite extends AnyFunSuite {
	test("elem result should have passed with"){
    	val elem = elem('x', 2, e)
        assert(ele.width == 2)
    }
}

스칼라 테스트에서 중심적인 개념은 suite이다. 테스트는 시작해서 성공하거나, 실패하거나 결과를 기다림, 혹은 취소될 수 있다.
트레이트 suite는 테스트들을 실행하기 위해 사전에 준비된 '생명 주기 메서드'들을 선언한다. 스칼라 테스트는 다른 테스트 스타일을 지원하기 위해 Suite를 확장하고 생명주기 메서드를 오버라이드하는 style trait를 지원한다.

충분한 정보를 제공하는 실패 보고

위쪽에서 assert문을 실패하면 AssertionError를 발생시키는 것을 알게되었다.

위의 코드처럼 조건이 틀리면 에러를 발생시킨다. 하지만, 에러 메시지만을 보고서는 어디서 어떤 오류가 발생했는지 알기 힘들다.
즉, 단언문이 실패한다면 파일명, 실패한 단언문의 줄 번호, 정보가 담긴 오류 메시지를 출력해야 한다.
이를 위해서는 assertResult 메서드를 사용하면 된다.

위와 같이 assertResult를 사용하면 빨간 글씨로 어디서 어떤 값을 도출해 실패했는지 알 수 있다.
(이 내용 실습을 하며 오류를 많이 겪었는데 이를 해결하는 방법은 여기에 기술하였다.)

명세로 테스트하기

동작 주도 개발(BDD/Behavior Driven Development) 테스트 스타일은 기대하는 코드의 동작을 사람이 읽을 수 있는 명세로 작성 후, 코드가 그 명세에 따라 잘 작동하는 지 확인하는 테스트를 작성하는데 중심을 둔다.

import org.scalatest.flatspec.AnyFlatSpect
import org.scalatest.matchers.should.Matchers
import Element.elem

class ElementSpect extends AnyFlatSpect with Matchers {
	"A UniformElement" should "have a width equal to the passed value" in {
    	val ele = elem('x', 2, 3)
        ele.width should be (2)
    }
}

AnyFlatSpec에서는 명세절(specifier clause)를 사용해 테스트를 작성한다. 테스트할 주제에 대해 이름을 문자열로 붙인다. 그 후, should 또는 mustcan을 넣고 그 뒤에 해당 주제의 작동을 설명하는 문자열이 오고 그 다음 in이 온다. in 이후의 중괄호에 테스트할 코드를 작성한다.

📚 Reference

  • Programming in Scala 4/e - Chapter 14

0개의 댓글