Back_End(Ruby on Rails)

루비온레일즈 테스트 코드 작성하기(How to Write a Test Code for RoR)

swdream 2019. 11. 2. 15:21
반응형

먼저, 개발 환경에선 별도의 db 를 가지므로(test db), test db migration이 필요합니다.(아래 캡쳐 참조)

Test 환경 DB 마이그레이션하기

아래와 같이 터미널에서 해당 명령어로 실행합니다. rails 환경이 개발 환경임을 명시해줍시다. (그래야 test db 로 마이그레이션됩니다.)

$ rails db:migrate RAILS_ENV=test

단일 테스트 파일을 Rails에서 실행하기

test 디렉토리에 있는 모든 test file들을 일일히 실행하여 테스트할 필요는 없으므로 내가 작업중인 test 파일만을 손쉽게 작업할 수 있습니다.

아래와 같이 iTerm(Terminal)에서 bin/rails '해당 테스트 파일의 경로'로 실행합니다.(아래 예는 user_photo_question_test.rb 테스트 파일을 실행하여 테스트를 진행하는 코드입니다.)

$ bin/rails test test/controllers/api/V1/users_controller/user_profile_test/user_photo_question_test.rb


IntegrationTest 사용하기

Rails Framework에서 제공하는 Test 방식은 여러가지가 있지만(Unit Test, Functional Test, Integration Test), 이 중 Integration Test 기초 작성방법을 정리하고자 합니다.

Integration Test 를 사용하는 이유로는, 말 그대로 통합테스트라는 이름처럼 여러 개의 컨트롤러를 사용하면서 실제 유저의 예상 행동을 시나리오 대로 모방할 때 사용합니다.

보통은, user를 생성하여 그 유저가 api call 을 하는 것에 대해 응답이 잘 작동하는지를 테스트하니까, 백엔드 단에서 많이 쓰이는 테스트입니다.



테스트 하고자 하는 것은 유저가 '학교'라는 키워드를 검색하여 search_school api를 콜 했을 때 status code가 200으로 뜨는지 확인 하는 것입니다.
먼저 아래와 같이, 테스트의 메인이 되는 search_school_test.rb 파일을 test 디렉토리 내 적당한 위치에 생성합니다. Integration Test를 위해서는 ActionDispatch Namespace에 IntegrationTest를 상속하는 클래스를 만들어야 합니다.
해당 통합 테스트 클래스의 인스턴스가 실행될 때는 setup method로 모방행동을 할 유저, 테스트용 db에 담길 학교 샘플 데이터를 세팅하고자 합니다.
그 이후에는 test 'Test Description'  do (block) end 방식으로 block 내에 실행할 함수(유저의 행동)와 rails 내에서 정의된 assert로 시작하는 류의 method로 해당 행동이 맞는지 유/무를 검증합니다.
모듈화를 통해 메인이 될 테스트 파일은 추상화된 행동만을 setup method 내에 정의하도록 합니다.


<테스트의 메인이 될 search_schools_test.rb 파일>

test 디렉토리 내 만들어주고, 해당 클래스로 테스트 실행 시, setup -> test block -> teardown 순으로 실행됩니다.


<search_schools_test.rb 파일에서 유저나 학교 샘플 seeding 등 사전 정의가 필요한 기능을 search_schools_helper.rb 파일에 모듈화>

main test 파일에서 구체적인 인터페이스들은 최대한 모듈에 밀어 넣어 main test 파일의 가독성을 높여줍니다.


< Test 수행 시 터미널 화면 - 1번의 실행, 그리고 1번의 테스트 검증 통과, 0번의 실패가 결과입니다.>


이제 좀 더 메인 테스트 코드 파일인 search_schools_test.rb 에 대해 좀 더 구체적인 테스트 케이스를 생각해봅시다. 유저가 키워드를 검색하는 경우는 크게 아래와 같은 시나리오로 쪼개서 생각할 수 있습니다.

1. 유저가 검색한 키워드를 포함한 학교 이름이 있는 경우 → 검색 결과 데이터가 유저가 검색한 키워드를 포함하면서 나오는지 체크
2. 유저가 검색한 키워드가 공백인 경우 → 검색 결과 데이터가 공백으로 나오는지 체크 (즉, 공백으로 검색하는 경우에는 검색되는 학교가 없어야 합니다.)
3. 유저가 검색한 키워드를 포함하는 학교가 하나도 없는 경우 → 검색 결과 데이터가 공백으로 나오는지 체크(즉, 검색되는 학교가 하나도 없어야 합니다.)
이를, 코드로 표현하면 아래와 같습니다.

require_relative 'search_schools_helper'
class SearchSchoolTest < ActionDispatch::IntegrationTest
    include SearchSchoolHelper

# #setup은 Test method 수행 전 db 데이터나 유저 등을 생성하여 세팅하기 위한 method 입니다.
    def setup
        set_default_user
        set_default_schools
    end

# #teardown은 setup method를 통해 생성하여 테스트에 사용했던 데이터나 유저 등을 삭제하여, 테스트 이전 상태로 초기화 하는 method 입니다.
def teardown
        User.delete_all
        School.delete_all
    end

#유저가 검색한 키워드를 포함한 학교 이름이 있는 경우 → 검색 결과 데이터가 유저가 검색한 키워드를 포함하면서 나오는지 체크합니다.
    test 'check if school result contains specific keyword, 학교' do
        keyword = "학교"
        get "/api/v1/users/search_school", params: {keyword: keyword}, headers: @header
        assert_equal 200, status
        response_body = JSON.parse(@response.body)
        response_body["result"].each do |item|
            assert_match keyword, item["name"]
        end
    end

#유저가 검색한 키워드가 공백인 경우 → 검색 결과 데이터가 공백으로 나오는지 체크 (즉, 공백으로 검색하는 경우에는 검색되는 학교가 없어야 합니다.)
    test 'Search with Keword, Blank string' do
        get "/api/v1/users/search_school", params: {keyword: ""}, headers: @header
        assert_response :success
        response_body = JSON.parse(@response.body)
        assert_empty response_body["result"]
    end

#유저가 검색한 키워드를 포함하는 학교가 하나도 없는 경우 → 검색 결과 데이터가 공백으로 나오는지 체크(즉, 검색되는 학교가 하나도 없어야 합니다.)
    test 'Search with keword which is not included in the whole db' do
        keyword = "abc"
        get "/api/v1/users/search_school", params: {keyword: keyword}, headers: @header
        assert_response :success
        response_body = JSON.parse(@response.body)
        assert_empty response_body["result"]
    end
end

이와 같이 학교 검색 api 에 대해 좀 더 있을 법한 테스트 케이스를 세분화해서 각각의 테스트를 수행한 결과, 모두 통과(검증)이 된 것을 확인할 수 있습니다.(아래 테스트 코드 실행 결과 캡쳐 참조)

 

반응형