반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

TDD 관련 아티클을 정리하고 있는데 오늘로서 완료할 것 같네요.

이 글을 읽고 TDD 에 대해서 많이 개념이 잡힌것 같습니다.

 

TDD from starting from user stories - a top-down style 03

 

 

A sample

 

실제 샘플 코드를 한번 보죠. 웹 어플리케이션 관련 작업을 하고 있다고 가정해 봅시다. 여기 로그인 기능과 관련한 스토리가 있습니다.

 

유저가 웹 사이트에 로그인하려고 합니다. 이 때 그 유저는 등록된 유저를 위한 어떤 기능을 사용할 수 있게 됩니다.

 

이 스토리에 대한 acceptance criteria 를 보면

 

* Happy path: 성공적인 로그인
Given: 유저가 로그인 페이지로 감
When: 제대로 된 아이디와 패스워드를 입력하고 submit 함
Then: 유저는 성공했다는 메세지와 함께 로그인 하게 됨

 

* Username or password missing
Given: 유저가 로그인 페이지로 감
When: 아이디나 비밀번호를 입력하지 않고 submit 버튼을 누름
Then: 유저는 "username or password missing" 이라는 에러 메세지를 보게 됨

 

* Username or password incorrect
Given: 유저가 로그인 페이지로 감
When: 맞지 않는 아이디나 비밀번호를 입력하고 submit 버튼을 누름
Then:  유저는 “username or password is not correct” 라는 에러 메세지를 보게 됨

 

 


웹 어플리케이션을 만들기 위해 Ruby on Rail 을 사용한다고 가정해 봅시다. 우리는 이 스토리에 대해 쉽게 acceptance test를 사용할 수 있습니다.

 

<src lang="ruby">
Story "Login", %(
        As a user,
        I want to sign in the website,
        So that I can use registered user specific functionality) do

        @selenium = Selenium::SeleniumDriver.new("localhost", 4444, "*iexplore", "http://localhost", 10000);

      Scenario "user successfully login" do
        Given "correct username and password" do
            @selenium.start
            @selenium.open "http://localhost/users/login"
            @selenium.type "username", "someone"
            @selenium.type "password", "password"
        end

        When "login" do
            @selenium.click "submit"
        end

        Then "user logged in successfully" do
            @selenium.is_text_present "Welcome, someone!"
            @selenium.stop
        end

    end

    other scenarios...

end
</src>


rbehave는 ruby code를 사용해서 business acceptance criteria 를 표현하기 위해 사용하는 프레임워크가 rbehave 입니다. 이 테스트를 작성하고 난 후 run 하고 실패하는 것을 확인하게 됩니다. 이제 이 test를 pass 하도록 하기 위해 어떻게 해야 하는지를 생각 할 수 있습니다. 이 시점에서 로그인 하기 위한 UserController 와 action 그리고 User Model을 call 하는 것을 만들어야 할 것입니다. 일단 무엇인가 만들기로 결심하면 코딩을 시작하게 되겠죠.

 


<src lang="ruby">
def test_registered_user_should_able_to_sign_in_and_redirect_to_home_as_default
    post :login, :name => "someone", :password => "password"
    assert_equal "Welcome, someone!", flash[:notice]
end
</src>

 

여기서 테스트 하는 Users control의 로그인 action은 login을 perform 해야하고 flash notice를 set 해야 합니다. 그리고 나서 우리는 controller action쪽으로 갈 겁니다.

 

<src lang="ruby">
def signin
    user = User.authenticate(params[:name], params[:password])
    flash[:notice] = "Welcome, " + user.nickname + "!"
    redirect_to :controller => "home"
end
</src>

우리는 User model에게 authentication을 위임 합니다. 여기에 대한 테스트를 작성할 수 있겠죠.

<src lang="ruby">
def should_be_able_to_get_authenticated_user
    assert_equal users(:someone), User.authenticate("some user", "user's password")
    ...
end
</src>

 

이렇게 하면 쉽게 간단한 코드를 작성해서 이 authenticate method를 구현할 수 있습니다. 여기서 너무 exception handling에 대해 염려하실 필요는 없습니다. 좀 더 많은 테스트 케이스들을 만든 다음에 점차 우리의 코드를 점점 알차게 다듬을 겁니다.

 

지금까지 간단한 스토리에 대한 그럴듯한 시나리오를 implement 하는 과정을 보여드렸습니다. 조각조각 여러 부분으로 나눈 다음에 문제를 푸는 과정을 기억해 두세요. 한번에 한 조각식 일을 진행합니다. 우선 test를 먼저 작성하고 그것을 pass 하기 위해 가장 간단한 코딩을 찾습니다. 이렇게 함으로서 각 스텝마다 아주 confident 하게 일을 진행할 수 있게 됩니다. 그리고 지금 우리가 만들고 있는 것의 가치를 분명하게 볼 수 있구요.

 

 

Variations

 

Lack of tools support

 

가끔 테스팅 툴이 없어서 해당 어플리케이션에 대한 모든 시나리오에 대한 functional test를 작성할 수 없을 때가 있습니다. 이런 경우엔 좀 더 생각을 확장해서 이러한 문제를 해결해야 합니다. 예를 들어 전체 어플리케이션이 아니라 모듈들에 대해서 functional 테스트를 작성할 수 있습니다. 윈도우즈 어플리케이션에 대해서 적당한 functional test tool을 찾을 수 없다면 passive view 같이 우리의 코드를 어떤 패턴으로 organize 할 수 있을 겁니다. 그러면 view 를 통해 action을 perform 하지 않고도 functional test를 작성할 수 있게 됩니다. 또 다른 경우를 예로 들면 C/S rich client application에서 서버가 우리가 원하는 대로 작동하는지에 대해 체크하기 위해 중요한 모듈의 functionality를 테스트 할 수 있을 겁니다.

 

- Dev unit test -> add functional tests

- Extract writing functional tests from dev to tester

 

 

 

functional test를 작성하는 것은 QA들에게는 아주 매력적인 일이죠. 개발자들에게는 unit test를 작성하는게 그럴거구요. 둘 다 동시에 진행하면 좋을 겁니다. 전체 팀의 생산성이 아주 높아지겠죠. 일단 acceptance criteria 가 확정 되면 개발자들은 unit test들을 작성하고 tester들은 functional test들을 작성하게 되는거죠. 이 방법이 이상적인 방법입니다. 하지만 실제 상황에서는 이렇게 진행되기가 힘들죠. 아래 이런 접근법에서 만날 수 있는 몇가지 문제점들을 언급하겠습니다.


가끔 개발자들과 테스터들은 동시에(parallelly) 일을 합니다. 그러면 생산성이 아주 높아지겠죠. (다시 말하지만 이러기는 힘듭니다. 이렇게 하기 위해서는 개발자와 테스터들간의 커뮤니케이션이나 iteration이 좀 더 자주 있어야 합니다.)QA가 사용하는 툴에 따라 QA가  functional test suite 를 만들고 유지보수 하기 위해 더 프로그래밍 실력이 좋아야 하는 경우도 있습니다. 만약 QA가 그렇게 프로그래밍 실력이 뛰어나지 않다면 새로 개발된 기능들에 대해 QA가 개발자를 따라잡기에 어렵습니다. 만약 개발자가 스토리를 아주 빠르게 deliver 하면 QA들의 일은 좀 더 어려워 질 겁니다.

이런 문제가 생기게 될 경우 이를 해결하는 방법이 있는데요. 그 중 하나는 개발자들에게 약간의 functional test들을 작성하고 유지 보수 하도록 하는 겁니다. 그것을 개발자의 build 에 통합하고 개발자들이 그 테스트들을 pass 하도록 하게끔 만드는 거죠.

반응형