일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 파이썬
- CORDA
- Adapter 패턴
- 파이썬 데이터분석
- 스칼라 강좌
- Actor
- 스칼라 동시성
- hyperledger fabric
- Hyperledger fabric gossip protocol
- Play2 로 웹 개발
- 그라파나
- 스칼라
- akka 강좌
- 하이퍼레저 패브릭
- 이더리움
- 스위프트
- play2 강좌
- 하이브리드앱
- 주키퍼
- 파이썬 강좌
- play 강좌
- Golang
- 플레이프레임워크
- 파이썬 동시성
- 엔터프라이즈 블록체인
- 파이썬 머신러닝
- 블록체인
- Play2
- 안드로이드 웹뷰
- Akka
- Today
- Total
HAMA 블로그
specs2 로 하는 유닛테스트 (번역) 본문
specs2 로 어플리케이션 테스트하기
어플리케이션 위한 테스트를 작성하는것은 개발 프로세스에 포함 될 수 있다. 플레이는 테스트 작성을 가능한 쉽게 할 수 있도록 기본 테스트 프레임워크를 제공한다.
살펴보기
테스트를 위한 파일의 위치는 "test" 폴더이다. 거기엔 2개의 샘플 테스트파일이 이미 존재하는데 당신 자신의 테스트를 작성하기 위한 템플릿으로 사용될 수 있을 것 이다.
플레이 콘솔에서 테스트를 실행 할 수 있다. (IntelliJ 같은 툴에서 실행도 가능)
- * 모든 테스트를 실행하기 위해
test
을 run 하라. - * 하나의 테스트 클래스를 실행하기 위해서는 run
test-only
를 하고 이어서 클래스이름을 써라.
다음과 같이test-only my.namespace.MySpec
. - * 오직 실패한 테스트를 돌리기 위해서
test-quick
. - * 테스트를 이어서 계속하기 위해
~test-quick
. - *
FakeRequest
같은 테스트 헬퍼에 접근하기위해 runtest:console
.
SBT 기반의 플레이를 테스트 하는것과 관련된 전체 문서는 testing SBT 를 참고 하시라
specs2 사용하기
플레이 specs2 를 사용하기 위해 의존성을 다음과 같이 추가하라.
libraryDependencies += specs2 % Test
specs2 는 테스트들이 specifications 로 구성되어 있는데 이것은 다양한 코드패스들을 통해 테스트기반한 시스템을 실행하는 여러가지 예제를 포함한다.
Specifications 는 Specification
trait 를 상속하였으며 should/in format 을 사용한다.
import org.specs2.mutable._
class HelloWorldSpec extends Specification {
"The 'Hello world' string" should {
"contain 11 characters" in {
"Hello world" must have size(11)
}
"start with 'Hello'" in {
"Hello world" must startWith("Hello")
}
"end with 'world'" in {
"Hello world" must endWith("world")
}
}
}
Specifications 는 IntelliJ IDEA (using the Scala plugin) 또는 Eclipse (using the Scala IDE) 에서도사용할 수 있다. 자세한건 다음링크를 참조하라.IDE page .
Note: presentation compiler 버그때문에 이클립스에서테스트들은 반드시 specific format 을 정의해야한다.
- 패키지는 반드시 디렉토리 패스와 동일해야한다.
- specification 반드시
@RunWith(classOf[JUnitRunner])
주석과 같이 사용되야한다.
여기 이클립스를 위한 올바른 specification 을 보자:
package models // this file must be in a directory called "models"
import org.specs2.mutable._
import org.specs2.runner._
import org.junit.runner._
@RunWith(classOf[JUnitRunner])
class ApplicationSpec extends Specification {
...
}
Matchers
반드시 example 결과를 리턴해야한다. 보통 must
을 포함한 문장을 보게 될것이다.
"Hello world" must endWith("world")
must
키워드를 가진 평가식은 matche
로 알려져있다. Matchers 는 example result 를 리턴하며, 성공 혹은 실패이다. 만약 result 를 리턴하지 않으면 컴파일하지 않을것이다.
가장 유용한 매쳐는 match results이다. 동등성 체크하는데 사용하며 Option 과 Either 그리고 예외가 발생했는지를 체크하기위해 result 를 확인한다.
optional matchers 도 있으며 XML 와 JSON matching 도 수행한다.
Mockito
Mocks 은 유닛테스트를 외부 디펜던시와 분리시키기 위해 사용된다. 예를들어 클래스가 외부 데이터 클래스에 의존적이라고 할때 완전한 데이타서비스 객체를 만드는것을 대신해서 적절한 가짜 데이터를 사용 할 수 있게 한다.
Mockito 는 specs2 에 디폴트 mocking library로 추가되어있다.
Mockito를 사용하기위해 다음 import 를 추가하자.
import org.specs2.mock._
다음과 같이 목을 만들 수 있다.
trait DataService {
def findData: Data
}
case class Data(retrievalDate: java.util.Date)
import org.specs2.mock._
import org.specs2.mutable._
import java.util._
class ExampleMockitoSpec extends Specification with Mockito {
"MyService#isDailyData" should {
"return true if the data is from today" in {
val mockDataService = mock[DataService]
mockDataService.findData returns Data(retrievalDate = new java.util.Date())
val myService = new MyService() {
override def dataService = mockDataService
}
val actual = myService.isDailyData
actual must equalTo(true)
}
}
}
Mocking 은 특별히 클래스의 공개 메소드를 테스팅하는데 유용하다. Mocking objects 와 private methods 도 가능하지만 좀 어렵다.
모델 유닛 테스팅
플레이는 특별한 데이타베이스 데이터 접근 레이어를 사용하기 위한 모델을 요구하진 않는데 , 만약 어플리케이션이 Anomr이나 Slick 을 사용한다면, 종종 모델은 내부적으로 데이타접근을 위한 참조를 가질 것이다.
import anorm._
import anorm.SqlParser._
case class User(id: String, name: String, email: String) {
def roles = DB.withConnection { implicit connection =>
...
}
}
유닛테스팅을 위해 이 경우는 roles
메소드를 목으로 만들 수 있다.
일반적인 접근법은 데이타베이스로부터 모델들을 고립시켜서 로직을 테스트하는것이다.
case class Role(name:String)
case class User(id: String, name: String, email:String)
trait UserRepository {
def roles(user:User) : Set[Role]
}
class AnormUserRepository extends UserRepository {
import anorm._
import anorm.SqlParser._
def roles(user:User) : Set[Role] = {
...
}
}
그리고 서비스를 통해 그들 (목) 에 접근한다.
class UserService(userRepository : UserRepository) {
def isAdmin(user:User) : Boolean = {
userRepository.roles(user).contains(Role("ADMIN"))
}
}
이런 방식으로 isAdmin
메소드는 Mock(목) UserRepository
를 주입받고 테스팅 된다
object UserServiceSpec extends Specification with Mockito {
"UserService#isAdmin" should {
"be true when the role is admin" in {
val userRepository = mock[UserRepository]
userRepository.roles(any[User]) returns Set(Role("ADMIN"))
val userService = new UserService(userRepository)
val actual = userService.isAdmin(User("11", "Steve", "user@example.org"))
actual must beTrue
}
}
}
컨트롤러 유닛 테스트
컨트롤러들이 정규 클래스라면 쉽게 플레이 테스트 헬퍼를 이용하여 유닛테스트를 할 수 있다. 하지만 만약 컨트롤러들이 또다른 클래들에 의존적이라면 dependency injection 를 사용할 수 있다. 이것은 그 의존성을 목(Mock) 으로 만들어 줄 것이다.
class ExampleController extends Controller {
def index() = Action {
Ok("ok")
}
}
요렇게 테스트 할 수 있다
import play.api.mvc._
import play.api.test._
import scala.concurrent.Future
object ExampleControllerSpec extends PlaySpecification with Results {
"Example Page#index" should {
"should be valid" in {
val controller = new ExampleController()
val result: Future[Result] = controller.index().apply(FakeRequest())
val bodyText: String = contentAsString(result)
bodyText must be equalTo "ok"
}
}
}
EssentialAction 유닛테스트
Action
과 Filter
를 테스팅 하기 위하여 EssentialAction
이 활용 된다.
Helpers.call
다음과 같이 사용된다.
object ExampleEssentialActionSpec extends PlaySpecification {
"An essential action" should {
"can parse a JSON body" in new WithApplication() {
val action: EssentialAction = Action { request =>
val value = (request.body.asJson.get \ "field").as[String]
Ok(value)
}
val request = FakeRequest(POST, "/").withJsonBody(Json.parse("""{ "field": "value" }"""))
val result = call(action, request)
status(result) mustEqual OK
contentAsString(result) mustEqual "value"
}
}
}
https://www.playframework.com/documentation/2.5.x/ScalaTestingWithSpecs2 번역
'PlayFramework2' 카테고리의 다른 글
[Play2] Action composition (번역) (0) | 2016.09.28 |
---|---|
Play2.4 로 웹 개발 시작하기 - (4) 로깅처리 (0) | 2016.09.27 |
Play2.4 로 웹 개발 시작하기 - (3) 나의 프로젝트 만들기 (0) | 2016.08.27 |
Play2.4 로 웹 개발 시작하기 - (2) 프로젝트 살펴보기 (0) | 2016.08.27 |
Play2.4 로 웹 개발 시작하기 - (1) 설치 및 프로젝트 만들기 (0) | 2016.08.27 |