첫 번째 MSPEC 사양을 올바르게 작성하고 있습니까?
문제
첫 번째 MSPEC 사양을 작성하고 있으며 몇 가지 지침을 원했습니다. 사양을 "보류중인"상태로 남겨 두었지 만 컨텍스트가 작성되었습니다. 개선 사항이 있습니까?
참고로, 이것은 이야기와 첫 번째 시나리오입니다.
Story: "Blog admin logs in to the system"
As a blog writer
I want to be able to log in to my blog
So that I can write posts and administer my blog
Scenario: "Logs in from the login page"
Given the user enters in correct credentials for a user in the system
When the user clicks the "Login" button
Then log the user in and redirect to the admin panel with a message
stating that he logged in correctly
그리고 MSPEC 코드 (일부 부품이 snipped), mspec를 별칭해야한다는 것을 알았습니다. It
충돌로 인한 대표 Moq.It
:
using MoqIt = Moq.It;
using ThenIt = Machine.Specifications.It;
[Subject("User tries logging in")]
public class When_user_enters_valid_credentials : With_user_existing_in_membership
{
protected static ActionResult result;
Because of = () =>
{
result = loginController.Login(validUsername, validPassword);
};
ThenIt should_log_the_user_in;
ThenIt should_redirect_the_user_to_the_admin_panel;
ThenIt should_show_message_confirming_successful_login;
}
public abstract class With_user_existing_in_membership
{
protected static Mock<ISiteMembership> membershipMock;
protected static string validUsername;
protected static string validPassword;
protected static LoginController loginController;
Establish context =()=>
{
membershipMock = new Mock<ISiteMembership>();
validUsername = "ValidUsername";
validPassword = "ValidPassword";
//make sure it's treated as valid usernames and password
membershipMock
.Setup<bool>(m => m.Validate(
MoqIt.Is<string>(s => s == validUsername),
MoqIt.Is<string>(s => s == validPassword)))
.Returns(true);
loginController = new LoginController(membershipMock.Object);
};
}
해결책
맥락이 좋아 보인다. 나는 당신이 충돌을 해결하는 방식이 마음에 듭니다 It
별명으로. 나는 MOQ 별칭이 개선 될 수 있다고 주장한다. 문장과 같은 것을 고려하십시오. 예를 들어, Param.Is<T>
또는 Value.Is<T>
.
코드 스 니펫이있는 일부 메모는 전체 사양이 바닥에 다시 작성되었습니다.
시나리오는 당신입니다 Subject
주제는 이야기의 시나리오가 될 수 있습니다. 또한 테스트 실행 보고서 (특히 HTML 보고서의 NIC)와 함께 렌더링됩니다.
[Subject("Login Page")]
"지명 된 기본 클래스"와 함께 시간을 낭비하지 마십시오.
MSPEC의 제작자 인 Aaron Jensen, 되돌아갔습니다 "with"구문을 완전히 사용하는 것입니다. 컨텍스트 클래스 이름은 보고서에 대해 표시되지 않으므로 의미있는 이름을 발명하는 데 시간을 보내지 마십시오.
public abstract class MembershipContext
주어진은 사양 클래스 이름입니다
이야기에서 주어진 후 구체적인 사양 클래스의 이름을 지정하십시오. 특히 기본 클래스 이름이 어디에서나보고되지 않기 때문에 보고서에서 컨텍스트의 절반을 잃을 수 있습니다! 또한 테스트중인 시스템 이름을 컨텍스트 클래스 이름으로 두지 않아야합니다. 이것은 당신의 맥락이 테스트중인 시스템을 리팩토링하기 위해 더 친근하게 만듭니다.
public class When_an_existing_user_enters_valid_credentials
기본 사양 클래스에는 일반 초기화 만 포함되어야합니다
종종 불필요합니다. 그들은 배열과 행동 단계를 분리시킵니다. 조롱 된 종속성 설정과 같은 공통 필드 초기화에 기본 클래스를 사용하십시오. 그러나 기본 클래스에서 동작을 조롱해서는 안됩니다. 그리고 컨텍스트 별 정보를 기본 클래스에 넣어서는 안됩니다. 예에서는 사용자 이름/비밀번호입니다. 이렇게하면 잘못된 자격 증명으로 두 번째 컨텍스트를 만들 수 있습니다.
Establish context = () =>
{
membership = new Mock<ISiteMembership>();
loginController = new LoginController(membership.Object);
};
콘크리트 사양 클래스의 필드는 개인이어야합니다
시험에서 언어의 "의식"을 줄입니다. 사양의 해당 부분이 대부분의 이야기를 들려 주므로 모든 MSPEC 특정 대표단 아래에 배치해야합니다.
static ActionResult result;
사양 점검
여기의 사양은 글로벌 컨텍스트를 설정하는 훌륭한 예입니다. MembershipContext
사양과 관련된 컨텍스트에서 상속 (따라서 추가 Establish
).
[Subject("Login Page")]
public class When_an_existing_user_enters_valid_credentials : MembershipContext
{
Establish context = () =>
{
membership
.Setup<bool>(m => m.Validate(
Param.Is<string>(s => s == username),
Param.Is<string>(s => s == password)))
.Returns(true);
};
Because of = () => result = loginController.Login(username, password);
It should_log_the_user_in;
It should_redirect_the_user_to_the_admin_panel;
It should_show_message_confirming_successful_login;
static ActionResult result;
const string username = "username";
const string password = "password";
}
public abstract class MembershipContext
{
Establish context = () =>
{
membership = new Mock<ISiteMembership>();
loginController = new LoginController(membership.Object);
};
protected static Mock<ISiteMembership> membership;
protected static LoginController loginController;
}