【问题标题】:What are some popular naming conventions for Unit Tests? [closed]单元测试有哪些流行的命名约定? [关闭]
【发布时间】:2010-09-10 21:52:03
【问题描述】:

一般

  • 所有测试都遵循相同的标准。
  • 清楚每个测试状态是什么。
  • 具体说明预期行为。

示例

1) MethodName_StateUnderTest_ExpectedBehavior

Public void Sum_NegativeNumberAs1stParam_ExceptionThrown() 

Public void Sum_NegativeNumberAs2ndParam_ExceptionThrown () 

Public void Sum_simpleValues_Calculated ()

来源:Naming standards for Unit Tests

2) 用下划线分隔每个单词

Public void Sum_Negative_Number_As_1st_Param_Exception_Thrown() 

Public void Sum_Negative_Number_As_2nd_Param_Exception_Thrown () 

Public void Sum_Simple_Values_Calculated ()

其他

  • Test 结束方法名称
  • 以类名开头的方法名

【问题讨论】:

标签: unit-testing naming-conventions


【解决方案1】:

我倾向于使用MethodName_DoesWhat_WhenTheseConditions 的约定,例如:

Sum_ThrowsException_WhenNegativeNumberAs1stParam

但是,我确实看到很多是让测试名称遵循单元测试结构

  • 安排
  • 行动
  • 断言

也遵循 BDD / Gherkin 语法:

  • 给定
  • 何时
  • 那么

将以如下方式命名测试:UnderTheseTestConditions_WhenIDoThis_ThenIGetThis

你的例子:

WhenNegativeNumberAs1stParam_Sum_ThrowsAnException

但是我更喜欢将要测试的方法名称放在第一位,因为这样测试可以按字母顺序排列,或者按字母顺序显示在 VisStudio 的成员下拉框中,并且 1 方法的所有测试都组合在一起。


无论如何,我喜欢用下划线分隔测试名称的主要部分,而不是每个单词,因为我认为它更易于阅读和了解测试的重点。

换句话说,我喜欢:Sum_ThrowsException_WhenNegativeNumberAs1stParam 优于 Sum_Throws_Exception_When_Negative_Number_As_1st_Param

【讨论】:

    【解决方案2】:

    这也值得一读:Structuring Unit Tests

    该结构对每个被测试的类都有一个测试类。这不是那么不寻常。但对我来说不同寻常的是,他为每个正在测试的方法都有一个嵌套类。

    例如

    using Xunit;
    
    public class TitleizerFacts
    {
        public class TheTitleizerMethod
        {
            [Fact]
            public void NullName_ReturnsDefaultTitle()
            {
                // Test code
            }
    
            [Fact]
            public void Name_AppendsTitle()
            {
                // Test code
            }
        }
    
        public class TheKnightifyMethod
        {
            [Fact]
            public void NullName_ReturnsDefaultTitle()
            {
                // Test code
            }
    
            [Fact]
            public void MaleNames_AppendsSir()
            {
                // Test code
            }
    
            [Fact]
            public void FemaleNames_AppendsDame()
            {
                // Test code
            }
        }
    }
    

    原因如下:

    一方面,这是保持测试井井有条的好方法。所有的 方法的测试(或事实)组合在一起。例如,如果 您使用 CTRL+M、CTRL+O 快捷键折叠方法体,您可以 轻松扫描您的测试并像阅读代码规范一样阅读它们。

    我也喜欢这种方法:

    MethodName_StateUnderTest_ExpectedBehavior

    所以也许适应:

    StateUnderTest_ExpectedBehavior

    因为每个测试都已经在一个嵌套类中

    【讨论】:

    • 对于那些在 Visual Studio 中使用 Resharper 的测试运行器的用户,他们使用 8.x 中的嵌套测试类修复了错误。从那时起,这成为了我的首选结构。
    • 使用 MethodName_StateUnderTest_ExpectedBehavior 方法使名称变得很长是否重要?如“InitializeApiConfiguration_MissingApiKey_IllegalArgumentException”。这真的是一个很好的测试名称吗?
    【解决方案3】:

    我对测试命名空间、类和方法使用“T”前缀。

    我尽量保持整洁并创建复制命名空间的文件夹,然后为测试创建一个测试文件夹或单独的项目,并为基本测试复制生产结构:

    AProj
       Objects
          AnObj
             AProp
       Misc
          Functions
             AFunc
       Tests
          TObjects
             TAnObj
                TAnObjsAreEqualUnderCondition
          TMisc
             TFunctions
                TFuncBehavesUnderCondition
    

    我可以很容易地看出某事是一个测试,我确切地知道它属于哪个原始代码,(如果你不能解决这个问题,那么无论如何测试都太复杂了)。

    它看起来就像接口命名约定,(我的意思是,你不会对以“I”开头的东西感到困惑,也不会与“T”混淆)。

    不管有没有测试,编译都很容易。

    不管怎样,理论上还是不错的,对于小型项目也很有效。

    【讨论】:

    • 有趣的方法。有些人可能会争辩说 T 前缀与您在泛型中使用的约定冲突(例如 func(T1, T2, TResult)),但我个人不在乎,只要团队内部达成共识。名称很短,这也使内容更具可读性。
    • 对我来说太匈牙利了(符号)。此外,ad stung 指出,前缀 T 用于泛型类型参数。
    • 我同意,匈牙利符号已被贬低,并且由于与标准泛型类型参数的冲突,我没有看到在这种情况下应用异常(就像接口一样)。
    【解决方案4】:

    我确实像使用“PascalCasing”的其他方法一样命名我的测试方法,没有任何下划线或分隔符。我将后缀 Test 留给该方法,因为它没有增加任何价值。该方法是测试方法由属性TestMethod指示。

    [TestMethod]
    public void CanCountAllItems() {
      // Test the total count of items in collection.
    }
    

    由于每个 Test 类应该只测试一个其他类,我将类的名称留在方法名称之外。包含测试方法的类的名称与被测类类似,后缀为“Tests”。

    [TestClass]
    public class SuperCollectionTests(){
        // Any test methods that test the class SuperCollection
    }
    

    对于测试异常或不可能的操作的方法,我在测试方法前加上单词Cannot

    [TestMethod]
    [ExpectedException(typeOf(ArgumentException))]
    public void CannotAddSameObjectAgain() {
      // Cannot add the same object again to the collection.
    }
    

    我的命名约定基于 Bryan Cook 的文章 "TDD Tips: Test Naming Conventions & Guidelines"。我发现这篇文章很有帮助。

    【讨论】:

    • +1 链接到我的帖子——尽管在您的测试中没有必要使用“测试”前缀。确保您的测试指定了预期的行为。例如,CanRetrieveProperCountWhenAddingMultipleItems()
    • 我不喜欢它,因为它不包含预期的行为
    【解决方案5】:

    我非常赞同这个人。您使用的命名约定是:

    • 清楚每个测试状态是什么。
    • 关于预期行为的具体说明。

    测试名称还需要什么?

    Ray's answer 相反,我认为 Test 前缀是不必要的。这是测试代码,我们知道。如果你需要这样做来识别代码,那么你有更大的问题,你的测试代码不应该和你的生产代码混在一起。

    至于长度和下划线的使用,它的测试代码,谁在乎呢?只有你和你的团队会看到它,只要它是可读的,并且清楚测试在做什么,继续! :)

    也就是说,我对测试还是很陌生,blogging my adventures with it :)

    【讨论】:

    • “只要它可读、清晰”和“谁……在乎”略有矛盾。好吧,当它不可读和清晰时,每个人都在乎,所以这很重要。 :-)
    • 前缀的一个附加参数。当您在 IDE 中搜索文件时,您可以从 Test 和您的类名开始轻松搜索测试用例。如果类名和测试类名相同,我们将总是不得不暂停并读取两个文件的路径
    • @THISUSERNEEDSHELP 我认为您的观点可以通过像 src/libssrc/tests 这样的良好文件夹结构轻松克服。我知道一些测试运行器框架确实需要像 test 这样的前缀来识别测试代码,因此在这些情况下无法避免,但对于其余情况,它可能是重复的 no required 前缀。
    • @negrotico19 当你 Search Everywhere (shift shift) 或 Find a Class By Name (CMD O) 时,我正在考虑 IntelliJ 中的情况。我知道它通过文件夹结构或模块结构来区分,但是当我们搜索某些内容时,我们已经知道要搜索什么。例如,如果我正在寻找一个测试,我想将我的搜索限制为test,然后搜索名称,而不是搜索名称并然后通过眼睛手动过滤掉测试。这是一个很小的区别,但是“测试[类名]”要容易得多,并且只弹出一个并减少心理负担
    【解决方案6】:

    第一组名称对我来说更具可读性,因为 CamelCasing 分隔单词,而下划线分隔命名方案的各个部分。

    我也倾向于在某处包含“Test”,无论是在函数名中,还是在封闭的命名空间或类中。

    【讨论】:

    • @Frank methodName = camelCase MethodName = PascalCase
    • @metro-smurf:有趣的区别,我从未听说过使用 PascalCase 一词,而且我已经这样做了很长时间。我只看到微软开发者圈子里出现了 PascalCase 这个词,你是这样做的吗?
    • Pascal Casing 和 Camel Casing 的历史(来自:Brad Abrams - blogs.msdn.com/brada/archive/2004/02/03/67024.aspx)... “在框架的初始设计中,我们就命名风格进行了数百小时的辩论。为了促进这些“我们创造了许多术语。由于 Anders Heilsberg(Turbo Pascal 的原始设计师)是设计团队的关键成员,因此我们选择 Pascal Casing 一词来表示 Pascal 编程语言普及的套管样式也就不足为奇了。”
    【解决方案7】:

    只要你遵循一个单一的做法,这并不重要。通常,我为一个方法编写一个单元测试,涵盖一个方法的所有变体(我有简单的方法;),然后为需要它的方法编写更复杂的测试集。因此,我的命名结构通常是 test(JUnit 3 的保留)。

    【讨论】:

      猜你喜欢
      • 2010-09-10
      • 1970-01-01
      • 2012-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-12
      相关资源
      最近更新 更多