BDD场景中的Given语句是否有效或仅验证状态?
例如,请考虑此示例:“鉴于我已登录”
步骤定义是否应该记录用户,还是应该仅验证我是否已登录?
如果它只应该验证我已登录,那么我该如何实际登录?
答案 0 :(得分: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; }
}
Authenticator Class:
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 :(得分:1)
在RSpec样式语法中,当我说“BDD”测试时,我想到的是,“给定”将是“描述”或“上下文”块的一部分,该块负责将测试的组件放入正确的状态,不负责在该状态下进行任何断言或验证组件的行为。
“给定”将执行设置组件的工作,然后使用“it”或“should”来验证某些行为。
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
我认为如果Ruby和RSpec对您有用,Jared描述了构建BDD测试的良好结构:http://blog.carbonfive.com/2010/10/21/rspec-best-practices/