[RoR 학습] 7장 검증과 테스트

루비온 레일스 학습 사용 교재: 『레일스와 함께하는 애자일 웹 개발』

긴 가방끈을 메고 공부하는 입장이라 일반 사용자들을 대상으로 하는 서비스를 운영해 본 경험이 없기에 테스트라는 이슈는 사실 내게 그리 중요한 이슈로 다가온 적이 거의 없다. 다만 책과 풍문을 통해 얻는 간접적 지식을 통해 테스트의 중요성을 인식하고 있는 수준이다. 어찌 됬든 솔직한 내 개발 습관은 당장의 수업 텀프로젝트 목표를 위한 개발에 집중하는 일이 주였을 뿐 테스트는 사실 거리가 멀었다.air jordan retro

하지만 이 교재에서는 아직 제대로 레일스에서 배운 것도 없는 것 같은데 벌써부터 테스팅에 대해서 이야기를 한다. 실상 레일스가 가지고 있는 장점 중 하나는 개발 초기부터 테스트를 할 수 있는 완벽한 서포트를 하고 있다는 점이다. 7장을 통해서 레일스의 테스트 기능을 깊숙히 경험할 수 있다.

가장 기본적인 테스트의 대상은 사용자로부터 입력 받는 데이터가 모델에 적합한지를 검증하는 것이다. 책의 표현을 빌리자면 데이터는 자신이 정착하게 될 DB와 UI단 사이에 지키고 서 있는 모델을 반드시 통과하게 된다. 따라서 우리는 이 모델을 통해서 입력 데이터의 검증을 할 수 있다.
nike air jordan 16
본 학습에서 사용하는 모델은 “app/models/products.rb” 에 있다. 이 파일을 열면 아주 썰렁한 모델 클래스에 대한 선언만이 존재한다. 우리는 여기에 입력 데이터에 대한 검증 코드를 삽입한다.

 이 코드가 교재에 있는 검증 코드를 일단 주르륵 쓴 것이다. 코드를 보면 대충 감이 온다. 일단 “validataes”가 검증하기 위한 키워드가 된다. 그리고 뒤에 이어 검증하고자 하는 모델의 속성을 한 개 이상 나열하면 된다. 예를 들면 위 코드에서 2번째라인에 “:title, “description, :image_url”이 이에 해당한다. 그리고 바로 뒤에 검증을 위한 조건을 역시 하나 이상 나열할 수 있다.  5번째 라인을 보면 image_url 속성 뒤에 allow_blank와 format이라는 검증 조건이 붙어 있는 것을 확인할 수 있다.

검증 조건들의 키워드의 의미로부터 대강 무엇을 체크하는지 확인할 수 있다. 다음이 레일스에서 제공하는 검증 조건들의 일부 목록이다.ray ban wayfarer sizes

  • presence : 속성의 존재여부를 체크하는 것이다. (DB에서 not null과 같다고 보면 된다.)
  • uniqueness : 새로 입력될 속성값이 기존의 데이터 가운데 겹치는지를 확인한다.
  • numericality : 정수여부부를 체크한다.
  • length : 길이를 체크한다.
  • allow_blank: : 공백을 허용한다.

물론 위에서 열거한 목록 외에도 더 많은 검증 조건들이 있다. 또한 위와 같은 방식 말고 “validates of presence~”로 시작하는 다른 형태의 문법도 있다.

그런데 위의 코드들을 보면서 조금 혼동되는 부분이 있다. :presence 와 presence: 의 차이가 있는지 하는 점이다. 결론부터 말하자면 똑같다 다만 값을 대입하는 방법이 다르다. 전자와 같은 경우에는 예를 들면 “:presence => true”로 표현해야 하고 후자에는 “presence: true”로 표현해야 한다. 어떻게 해도 결과는 같다. 전자는 기존의 루비 문법으로 해쉬 형태로 값을 할당하는 것이고, 후자는 루비1.9에 오면서 새롭게 지원되는 문법형태라고 한다.

위의 검증 코드 중에서 가장 난해한 부분은 마지막이다. 마지막 검증은 이미지의 파일 경로의 마지막 확장자를 정규표현식을 통해서 검증하는 것이다. 위의 정규표현식을 간단히 해석해 보면 다음과 같다. 우선 정규표현식을 나타내기 위해서 “%r{정규표현식}” 과 같은 템플릿을 사용한다. 내용에서 백슬래쉬는 뒤에 나오는 .을 표현하기 위한 것이다. 정규표현식은에서 . 은 모든 문자에 해당되는 예약된 키워드이기 떄문에 순수하게 .을 매칭하기 위해서는 백슬래쉬를 반드시 붙여야 한다. 1그리고 뒤에 나오는 각각 jpg, gif, png는 파일 확장자이고 | 표시는 “또는”(or)을 표시하는 것이다. ‘\Z’는 문자열의 맨 마지막을 가리키게 하는 특수한 기능이다. 마지막으로 맨 뒤에 붙은 i는 대소문자 구분을 무시하라는 뜻. 결국 요약하면 입력된 이미지 경로 문자열의 끝이 “.jpg”, “.gif”, “.png” 가운데 대소문자 구분 없이 확인하는 표현식이다.

책에서는 ‘\Z’ 대신 $ 표시를 썼는데 똑같은 기능을 한다. 다만 $표시를 쓸 경우 “multiline” 옵션을 true로 반드시 추가 하지 않으면 에러가 뜬다. 이제 실제 애플리케이션을 서버 상에서 실행하고 나서 새로운 상품을 추가할 때 위 조건들을 지키지 않으면 아래와 같이 실시간으로 에러처리를 해준다.nike air max Low Cost

검증조건 확인

여기까지 하고 나서 “rake  test”를 하면 에러가 뜬다.  이유인 즉슨 레일스가 사전에 생성한 기능 테스트 케이스에서 위의 검증 조건을 맞추지 못한 경우가 있기 때문이다.  따라서 “test/controlles/products_controller_test.rb” 2 에서 위의 검증 조건을 맞출 수 있도록 코드를 수정해야 테스트에 문제가 없다. 코드를 들여다 보면 여러 기능 테스트들이 나열되어 있다. 문제가 된 부분은 상품 객체를 “생성(shoud create product)”, “갱신(shoud update product)”하는 테스트이다.  우선 위에서 설정한 검증 조건을 맞출 수 있도록 객체를 생성하고 이를 각각 생성, 갱신 테스트에 적용해야 한다. 적용한 후에 테스트를 실행하면 문제 없이 테스트를 통과할 수 있다.

다음은 단위테스트이다. C에서의 assert 문과 같이 루비에서도 동일한 키워드가 있다. assert 다음에 참인 조건이 나와야 한다. 만약 조건이 거짓일 경우 에러를 띄우게 된다. 단위테스트 코드는 책에서 설명하는 “test/units” 폴더와 달리 레일스 4에서는 test/model 안에서 확인할 수 있다.

ray ban sunglasses 3025

 test라는 키워드 뒤에 테스트에 대한 설명이 담긴 문자열이 뒤따라 온다. 그리고 do~end 구조 안에 테스트를 위한 코드가 있다. 첫번째 테스트 “Products attributes must not be empty”를 한 번 보자. 아무런 속성값 할당 없이 Products를 생성하였다. 당연히 유효하지 않은 생성이기 때문에 바로 이어지는 assert문에서 invalid? 조건을 통과한다는 것을 알 수 있다. 이어지는 assert문은 errors 배열 안에 각 속성 값에 대한 에러 값이 있는 지를 확인하는 any?를 사용하고 있다. 만약 위에 Products 객체를 초기값을 할당한 후에 “rake test:units”로 단위테스트를 실행하면 다음과 같은 에러메시지를 발견하게 될 것이다.

단위테스트 에러문구

세번째 테스트는 이미지 경로의 검증 조건을 실제 단위 테스트로 확인 한다. 미리 객체의 템플릿을 image의 경로 속성 값만 비워둔 채 이를 매개변수로 받는 함수 형태로 만들어 놓고, 조건에 맞는 이미지 경로와 맞지 않는 경로를 직접 테스트하는 코드이다.air jordan Sale

마지막으로 픽스쳐에 대해서 정리해보자. 픽스쳐는 레일스에서 테스트를 위해 준비해 둔 테스트 전용 데이터라고 생각하면 된다. 매번 테스트를 할 때 마다 임의의 값을 DB에 넣었다가 뺐다 하는 일은 참 번거로운 일이다. 레일스는 미리 “test/fixtures” 폴더 내에 모델의 테스트용 데이터를 입력할 수 있게 도와준다. 본 실습에 해당하는 Products 데이터 역시 YAML형식으로 products.yml 파일로 데이터가 저장되어 있음을 알 수 있다. “test/fixtures” 안에 픽스쳐를 만들어 두고서 단위테스트 파일 안에 “fixtures :(파일명)”을 표기하면 픽스쳐 데이터를 단위테스트에 활용할 수 있는 놀라운 기능이다.

7장에서는 오로지 테스트만 실습했다. Validates를 통한 모델 데이터 검증, assert를 활용한 단위테스트, 그리고 테스트를 돕기 위한 픽스쳐가 핵심이다. 이번 실습에 해당되는 소스는 깃헙에서  “second-iter” tag 로 확인할 수 있다.

https://github.com/jwj0831/rails-practice

Notes:

  1. http://blog.daum.net/creazier/15309380
  2. 교재에서는 test/functionals~ 였다. 아무래도 내가 사용하는 레일스4와는 폴더 구조가 다른 듯하다.