我遵循
的命名惯例MethodName_Condition_ExpectedBehaviour
在命名测试特定方法的单元测试时。
例如:
[TestMethod]
public void GetCity_TakesParidId_ReturnsParis(){...}
但是当我需要重命名测试方法时,像ReSharper这样的工具不能让我重命名那些测试。
有没有办法防止重命名后出现此类情况?比如更改ReSharper设置或遵循更好的单元测试命名约定等?
答案 0 :(得分:7)
最近的模式是通过他们测试的方法将测试分组到内部类中。
例如(省略测试属性):
public CityGetterTests
{
public class GetCity
{
public void TakesParidId_ReturnsParis()
{
//...
}
// More GetCity tests
}
}
有关详细信息,请参阅Structuring Unit Tests from Phil Haack's blog。
这种布局的巧妙之处在于,当方法名称发生变化时, 你只需要更改内部类的名称而不是全部 个别测试。
答案 1 :(得分:1)
我也从这次转换开始,但结果却感觉不是很好。现在我使用像should_return_Paris_for_ParisID
这样的BDD样式名称。
这使我的测试更具可读性,而且允许我重构方法名称而不用担心我的测试:)
答案 2 :(得分:0)
我认为这里的关键是应该进行测试。
你在标签中提到了TDD,所以我希望我们在这里努力坚持这一点。通过这种模式,你写的测试有两个目的:
支持您的代码一旦编写完成,您就可以重构,而不必担心您已经破坏了某些内容
指导我们更好地设计组件 - 首先编写测试真的会让您思考解决手头问题的必要条件。
我知道起初看起来这个问题是关于第一点,但我认为这是第二点。你遇到的问题是你已经测试了具体的组件,而不是合同。
在代码方面,这意味着我认为我们应该测试接口而不是类方法,否则我们会将测试暴露给与测试组件而不是合同相关的各种问题 - 继承策略,对象构造,以及重命名。
接口名称也会改变,但它们会比方法名称更加严格。 TDD给我们提供的不仅仅是通过测试工具支持变革的一种方式 - 它提供了洞察力,以实现我们可能以错误的方式进行变革!
以您提供的代码块为例:
[TestMethod]
public void GetCity_TakesParidId_ReturnsParis(){...}
{
// some test logic here
}
让我们说我们在对象 CityObtainer 上测试方法 GetCity() - 我什么时候设置了这个对象?我为什么这样做?如果我意识到 GetMatchingCity()是一个更好的名字,那么你就会遇到上面列出的问题!
我建议的解决方案是,我们通过使用接口来考虑这个方法在过程中对早期的真正含义:
public interface ICityObtainer
{
public City GetMatchingCity();
}
通过以这种“从外到底”的方式写作,我们不得不在此过程中更早地考虑我们想要的对象,并且它成为焦点应该减少其波动性。这并没有消除你的问题,但它可能会有所缓解(而且,我认为,无论如何,这是一种更好的方法)。
理想情况下,我们更进一步,在开始测试之前我们甚至不编写任何代码:
[TestMethod]
public void GetCity_TakesParId_ReturnsParis
{
ICityObtainer cityObtainer = new CityObtainer();
var result = cityObtainer.GetCity("paris");
Assert.That(result.Name, Is.EqualTo("paris");
}
这样,在我开始编写之前,我可以从组件中看到我真正想要的 - 如果 GetCity()不是我想要的,但是而 GetCityByID(),在此过程中会很明显。正如我上面所说,它并非万无一失,但它可能会减轻这种特殊情况的痛苦。
一旦你完成了这个,我觉得如果你改变方法的名称,那是因为你改变了合同的条款,这意味着你 必须返回并重新考虑测试(因为您可能不想更改它)。
(作为一个快速的附录,如果我们正在考虑使用TDD进行测试,那么 GetCity()内部会发生一些有大量逻辑的事情。考虑测试作为合同有助于我们将意图与实施分开 - 无论我们在界面背后发生什么变化,测试都将保持有效!)