C# 这是TDD的正确方法吗?

C# 这是TDD的正确方法吗?,c#,.net,model-view-controller,tdd,C#,.net,Model View Controller,Tdd,这里是TDD的新成员。只是需要一些指导,看看我是不是走对了路。我希望使用TDD将罗马数字字符串转换为整数。我有两个顾虑(另外,如果有人能指出其他顾虑,请指出): 我觉得我可能写了太多类似的测试,比如 I_返回1、II_返回2等。。我应该把这些结合起来吗 测验?或者数到20,我真的应该做20次测试吗 我重构得够多了吗?否则,有什么建议吗 private static readonly Dictionary<string, int> Specials = new Dictionary&

这里是TDD的新成员。只是需要一些指导,看看我是不是走对了路。我希望使用TDD将罗马数字字符串转换为整数。我有两个顾虑(另外,如果有人能指出其他顾虑,请指出):

  • 我觉得我可能写了太多类似的测试,比如 I_返回1、II_返回2等。。我应该把这些结合起来吗 测验?或者数到20,我真的应该做20次测试吗
  • 我重构得够多了吗?否则,有什么建议吗

    private static readonly Dictionary<string, int> Specials = new Dictionary<string, int>()
    {
        {"IV", 4},
        {"IX", 9}
    };
    
    public static int? Convert(string input)
    {
        if (input == null) return null;
    
        var processed = input;
        var counter = 0;
    
        foreach (var special in Specials)
        {
            if (!processed.Contains(special.Key)) continue;
    
            processed = processed.Replace(special.Key, "");
            counter = counter + special.Value;
        }
    
        for (int i = 0; i < processed.Length; i++)
        {
            if (processed[i] == 'X')
                counter = counter + 10;
            if (processed[i] == 'V')
                counter = counter + 5;
            if (processed[i] == 'I')
                counter++;
        }
    
        return counter;
    }
    

    首先,单元测试名称应该是有意义的,而不仅仅是描述代码

    II_返回_2
    没有解释测试试图保证什么<代码>II应解释为\u 2的罗马表示法\u更好地解释了业务规则

    这一点很重要,因为当你从一年前开始阅读测试名
    II_returns_2
    的代码时,你根本不知道为什么要写这个测试。(在这个简单的示例中,您可能会这样做,但在典型的应用程序中不会)

    接下来的事情是,方法名称将是相似的,但由于代码路径不同(应用程序根据罗马数字执行不同的分支),您需要进行不同的测试

    幸运的是,有两个不同的单元测试库支持使用属性定义一组不同的测试值

    这是一个来自中国的样品


    首先,单元测试名称应该是有意义的,而不仅仅是描述代码

    II_返回_2
    没有解释测试试图保证什么<代码>II应解释为\u 2的罗马表示法\u更好地解释了业务规则

    这一点很重要,因为当你从一年前开始阅读测试名
    II_returns_2
    的代码时,你根本不知道为什么要写这个测试。(在这个简单的示例中,您可能会这样做,但在典型的应用程序中不会)

    接下来的事情是,方法名称将是相似的,但由于代码路径不同(应用程序根据罗马数字执行不同的分支),您需要进行不同的测试

    幸运的是,有两个不同的单元测试库支持使用属性定义一组不同的测试值

    这是一个来自中国的样品

    重复从来都不是好的(),因此类似的试验应采用单一试验来表示。我不熟悉Microsoft的单元测试框架,但在NUnit中,您可以使用attribute编写如下内容:

    [TestFixture]
    public class RomanNumeralConverter_Tests
    {
       [TestCase("I", 1)]
       [TestCase("II", 2)]
       [TestCase("III", 3)]
       [TestCase("IV", 4)]
       [TestCase("V", 5)]
       [TestCase("VI", 6)]
       // etc...
       public void Convert_returns_decimal_representation(string roman, int expectedDecimal)
       {
          var result = Program.Convert(roman);
          Assert.AreEqual(expectedDecimal, result);
       }
    }
    
    重复从来都不是好的(),因此类似的试验应采用单一试验来表示。我不熟悉Microsoft的单元测试框架,但在NUnit中,您可以使用attribute编写如下内容:

    [TestFixture]
    public class RomanNumeralConverter_Tests
    {
       [TestCase("I", 1)]
       [TestCase("II", 2)]
       [TestCase("III", 3)]
       [TestCase("IV", 4)]
       [TestCase("V", 5)]
       [TestCase("VI", 6)]
       // etc...
       public void Convert_returns_decimal_representation(string roman, int expectedDecimal)
       {
          var result = Program.Convert(roman);
          Assert.AreEqual(expectedDecimal, result);
       }
    }
    

    算法怎么样?你认为还有改进的余地吗?@DrZeuso:这是CodeReview网站的一个问题。但是我会将
    特殊
    块移动到一个单独的非公共方法,然后使用
    开关
    语句而不是
    if
    语句进行另一个检查。算法如何?你认为还有改进的余地吗?@DrZeuso:这是CodeReview网站的一个问题。但是我会将
    特殊的
    块移动到一个单独的非公共方法,然后使用
    开关
    语句而不是
    if
    语句进行另一个检查。看起来算法中也有一些重复。你认为还有改进的余地吗?看起来算法中也有一些重复。你认为还有改进的余地吗?
    [TestFixture]
    public class RomanNumeralConverter_Tests
    {
       [TestCase("I", 1)]
       [TestCase("II", 2)]
       [TestCase("III", 3)]
       [TestCase("IV", 4)]
       [TestCase("V", 5)]
       [TestCase("VI", 6)]
       // etc...
       public void Convert_returns_decimal_representation(string roman, int expectedDecimal)
       {
          var result = Program.Convert(roman);
          Assert.AreEqual(expectedDecimal, result);
       }
    }