所以我开始发现TDD的bug,但我想知道我是否真的做对了……我似乎正在写很多的测试。
当然,测试越多越好,但我有一种感觉,我已经结束了。老实说,我不知道我还能继续写这些简单的重复测试多久。
例如,以下是来自my AccountController的LogOn操作:
public ActionResult LogOn(string returnUrl)
{
if (string.IsNullOrEmpty(returnUrl))
returnUrl = "/";
var viewModel = new LogOnForm()
{
ReturnUrl = returnUrl
};
return View("LogOn", viewModel);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult LogOn(LogOnForm logOnForm)
{
try
{
if (ModelState.IsValid)
{
AccountService.LogOnValidate(logOnForm);
FormsAuth.SignIn(logOnForm.Email, logOnForm.RememberMe);
return Redirect(logOnForm.ReturnUrl);
}
}
catch (DomainServiceException ex)
{
ex.BindToModelState(ModelState);
}
catch
{
ModelState.AddModelError("*", "There was server error trying to log on, try again. If your problem persists, please contact us.");
}
return View("LogOn", logOnForm);
}
非常不言自明。
然后,我有了下面的测试套件
public void LogOn_Default_ReturnsLogOnView()
public void LogOn_Default_SetsViewDataModel()
public void LogOn_ReturnUrlPassedIn_ViewDataReturnUrlSet()
public void LogOn_ReturnUrlNotPassedIn_ViewDataReturnUrDefaults()
public void LogOnPost_InvalidBinding_ReturnsLogOnViewWithInvalidModelState()
public void LogOnPost_InvalidBinding_DoesntCallAccountServiceLogOnValidate()
public void LogOnPost_ValidBinding_CallsAccountServiceLogOnValidate()
public void LogOnPost_ValidBindingButAccountServiceThrows_ReturnsLogOnViewWithInvalidModelState()
public void LogOnPost_ValidBindingButAccountServiceThrows_DoesntCallFormsAuthServiceSignIn()
public void LogOnPost_ValidBindingAndValidModelButFormsAuthThrows_ReturnsLogOnViewWithInvalidModelState()
public void LogOnPost_ValidBindingAndValidModel_CallsFormsAuthServiceSignIn()
public void LogOnPost_ValidBindingAndValidModel_RedirectsToReturnUrl()
是不是杀过头了?我甚至还没有展示服务测试!
我可以剔除哪些(如果有的话)?
蒂娅
查尔斯
发布于 2009-09-03 07:10:23
这完全取决于你需要/想要多少覆盖率,以及有多大的可靠性是一个问题。
这里是你应该问自己的问题:
关于第三个,我记得当我开始写单元测试的时候(我知道,和TDD不是一回事),我会有这样的测试:
string expected, actual;
TypeUnderTest target = new TypeUnderTest();
target.PropertyToTest = expected;
actual = target.PropertyToTest;
Assert.AreEqual<string>(expected, actual);
我本可以用我的时间做一些更有效率的事情,比如为我的桌面选择一张更好的墙纸。
我推荐这篇由ASP.net MVC书籍作者桑德森撰写的文章:
http://blog.codeville.net/2009/08/24/writing-great-unit-tests-best-and-worst-practises/
发布于 2009-09-03 07:09:33
我会说你做的比你可能必须做的要多一点。虽然测试代码可以采用的每一条可能的路径是很好的,但有些路径并不是很重要,或者不会导致行为上的真正差异。
在您的示例中,以LogOn(string returnUrl)为例
您要做的第一件事是检查returnUrl参数,如果该参数为null/空,则将其重新赋值为默认值。您真的需要整个单元测试来确保一行代码按预期运行吗?这不是一条容易打破的线。
大多数可能会破坏这一行的更改都会抛出编译错误。可以在该行中更改指定的缺省值(也许您稍后会认为"/“不是一个好的缺省值...但是在你的单元测试中,我打赌你是硬编码来检查"/“的,不是吗?因此,值的更改将需要在测试中进行更改...这意味着你不是在测试你的行为,而是在测试你的数据。
只需进行一次不提供参数的测试,即可实现对该方法行为的测试。这将命中例程的"set default“部分,同时仍在测试其余代码是否运行良好。
发布于 2009-09-03 06:55:33
这在我看来是正确的。是的,您将编写大量的单元测试,并且,开始时,它看起来像是大材小用和浪费时间;但坚持下去,这是值得的。你的目标应该是(而不仅仅是100%的代码覆盖率)是100%的函数覆盖率。然而..。如果你发现你为同一个方法编写了很多it,那么这个方法可能做得太多了。试着更多地分离你的关注点。根据我的经验,Action的主体应该只是创建一个类来做真正的工作。这才是UTs真正应该针对的类。
克里斯
https://stackoverflow.com/questions/1371755
复制相似问题