2011-03-02 2 views
0

BDD 시나리오의 Given 문이 작동하거나 상태 만 확인해야합니까?BDD 테스트에서 주어진 것은 작동하거나 상태 만 확인해야합니까?

이 단계 정의에서 사용자를 로그인해야 또는 그것은 단지 내가 로그인하고 있는지 확인해야합니다 "나는 로그인하고 있음을 감안할 때"

예를 들어,이 예제를 고려?

내가 로그인했는지 만 확인하면 로그인하는 방법은 무엇입니까?

+0

안녕하세요 :

describe ClassUnderTest do describe "some feature" do context "given that I am logged in" do before do sign_in Factory :user end it "has some behavior" do #make some assertion about the ClassUnderTest's behavior end end end end 

나는 루비와 RSpec에 당신을 위해 유용한 지 제라드가 BDD 여기에 테스트 구조화위한 좋은 구조를 설명 생각합니다. 그 이후로 결론에 도달 했습니까? 비슷한 질문이 있습니다. 나는 또 다른 예를 들겠습니다 : 나는 제품 페이지에 있다고 가정합니다. 예를 들어 그 상태에 도달하기 위해 모든 단계를 실행해야한다고 가정합니다. 로그인하여 제품 페이지로 이동하십시오. 어떤 경우 시나리오는 실제로 로그인 페이지에 있음을 감안할 때/유효한 자격 증명으로 로그인해야합니다. 그리고 제품 페이지로 이동합니다. 기본적으로 우리의 출발점은 항상 로그인 페이지입니다. 이것은 잘못된 생각이지만 ... –

답변

1

답변은 테스트하려는 대상에 따라 다릅니다. 이 예제는 오이가 아닌 것처럼 들리지만 BDD라는 용어를 사용했습니다. BDD를 상향식 단위 테스트와 연결합니다. 이 경우, 일종의 인증 클래스와 사용자 클래스가 있다고 가정합니다.

사용자 클래스 :

public class User : IUser 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public string Password { get; set; } 
} 

public interface IUser 
{ 
    int ID { get; } 
    string Name { get; } 
    string Password { get; } 
} 

인증 자 클래스 : 인증, 관리 권한 등을 호출하기위한

public class Authenticator : IAuthenticator 
    { 
     public Authenticator() 
     { 
      //Initialize and acquire some authentication mechanism (db, service, file, etc..) 
     } 

     public bool IsLoggedIn(IUser user) 
     { 
      return true; 
     } 
     public bool LoginUser(IUser user) 
     { 
      //Do real login. 
      return true; 
     } 

     public bool LogoutUser(IUser user) 
     { 
      //Do real logout. 
      return true; 
     } 
    } 

    public interface IAuthenticator 
    { 
     bool LoginUser(IUser user); 
     bool LogoutUser(IUser user); 
    } 

UserActions 클래스 :이 클래스와

public class UserActions 
{ 
    private readonly IAuthenticator _authenticator; 
    private readonly IUser _user; 
    //private Permissions Permissions; 

    public UserActions(IUser user) 
     : this(new Authenticator(), user) 
    { } 

    public UserActions(IAuthenticator authenticator, IUser user) 
    { 
     _authenticator = authenticator; 
     _user = user; 
    } 

    public bool Login() 
    { 
     var result = _authenticator.LoginUser(_user); 
     return result; 
    } 

    public void Logout() 
    { 
     _authenticator.LogoutUser(_user); 
    } 
} 

를, 내가 시도 것 로그인과 관련하여 UserActions 클래스의 동작 (NUnit 및 MOQ 사용)을 테스트합니다. 로그 아웃합니다. 이 예에서 어떤 작업이 수행되지 않지만, 예를 위해서, 풀러 구현 상상 :

[TestFixture] 
public class Tester 
{ 
    [Test] 
    public void CanLoginGoodUser() 
    { 
     IUser user = new User { ID = 1, Name = "Test1", Password = "good" }; 
     var authenticator = new Mock<IAuthenticator>(); 
     authenticator.Setup(a => a.LoginUser(user)).Returns(true); 

     var action = new UserActions(authenticator.Object, user); 
     action.Login(); 
     authenticator.Verify(a => a.LoginUser(It.Is<IUser>(u => u == user)), Times.AtLeastOnce()); 
    } 

    [Test] 
    public void WontLoginBadUser() 
    { 
     IUser user = new User { ID = 1, Name = "Test1", Password = "bad" }; 
     var authenticator = new Mock<IAuthenticator>(); 
     authenticator.Setup(a => a.LoginUser(user)).Returns(false); 

     var action = new UserActions(authenticator.Object, user); 
     action.Login(); 
     authenticator.Verify(a => a.LoginUser(It.Is<IUser>(u => u == user)), Times.AtLeastOnce()); 
    } 
} 

실제로 로그인하지 않거나 로그 아웃을. 내가하는 일은 인터페이스를 활용하여 클래스가 소비하는 클래스와 상호 작용할 때 클래스의 작동 방식을 보여주는 미리 준비된 응답을 제공하는 것입니다. 이 경우 인증 자 및 사용자 객체. 이 시점에서 필요가 없으므로 사용자 클래스를 조롱하지 않았습니다.

나는이 접근법에 대해 다른 사람들이 동의하지 않을 것이라고 확신하지만, 현재 내가하고있는 것입니다. 이는 상향식 테스트, 견고한 코드 커버 리지 및 클래스 디자인에 대한 분리 문제를 허용한다는 점에서 저에게 효과적입니다.

1

"BDD"테스트를 할 때 생각하는 RSpec 스타일 구문에서 "given"은 테스트 된 구성 요소를 가져 오는 "설명"또는 "컨텍스트"블록의 일부일 것입니다 올바른 상태로 만들어야하며 해당 상태의 구성 요소에 대한 어설 션 또는 동작 확인을 책임지지 않습니다.

"주어진"것은 구성 요소를 설정하고 일부 동작을 확인하는 "it"또는 "should"가 뒤따라야합니다. http://blog.carbonfive.com/2010/10/21/rspec-best-practices/

관련 문제