为 if else 语句编写单元测试

Sky*_*ire 2 c# unit-testing if-statement xunit.net

我是单元测试的新手,也是 C# 的新手,非常感谢有关如何编写单元测试以确保 AddGrade 方法中的逻辑正常工作的帮助。所以基本上如果成绩 >=0 和 <=100 那么成绩是有效的,它将被添加,其他任何东西都不是,它应该在控制台中显示一个错误。

我看过另一篇关于在 c# 中对 if-else 语句进行单元测试的帖子,并尝试从中解决这个问题,但如果我说实话,它让我感到困惑。我环顾网上等,并尝试了很多不同的方法来尝试解决这个问题,但我发现有时很难将人们的示例应用到我的代码中,所以我认为最好只是发布我的代码并获得一些帮助,任何帮助都会不胜感激:)

我正在使用 Xunit 进行单元测试。该项目在控制台中运行。

这是带有main方法的程序类

    using System;
using System.Collections.Generic;

namespace GradeBook
{
    class Program
    {
        static void Main(string[] args)
        {
            var book = new Book("Dave's");

            //add grade to the book
            book.AddGrade(90.5);
            book.AddGrade(80.5);
            book.AddGrade(70.5);
            book.AddGrade(60.5);

            var stats = book.GetStatistics();
            Console.WriteLine($"This Gradebooks name is {book.Name}");
            Console.WriteLine($"The highest grade is {stats.High:N1}");
            Console.WriteLine($"The lowest grade is {stats.Low:N1}");
            Console.WriteLine($"The average grade is {stats.Average:N1}");//N1,N2 etc. is number of decimal places
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我想为其编写单元测试的 AddGrade 方法所在的书籍类

    using System;
using System.Collections.Generic;

namespace GradeBook
{
    public class Book
    {
        public Book(string name)
        {
            grades = new List<double>();
            Name = name;
        }

        public void AddGrade(double grade)
        {
            if (grade >= 0 && grade <= 100)
            {
                grades.Add(grade);               
            }
            else
            {
                Console.WriteLine("Please enter a value between 0 and 100");
            }
        }

        public Statistics GetStatistics()
        {
            var result = new Statistics();
            result.Average = 0.0;
            result.High = double.MinValue;
            result.Low = double.MaxValue;
            

            foreach (var grade in grades)
            {
                Console.WriteLine($"{Name} grade is: {grade}");
                result.Low = Math.Min(grade, result.Low);
                result.High = Math.Max(grade, result.High);
                result.Average += grade;
                
                
            }
            result.Average /= grades.Count;
            return result;           
        }

        private List<double> grades = new List<double>() { };
        public string Name;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是统计类

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GradeBook
{
    public class Statistics
    {
        public double Average;
        public double High;
        public double Low;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我为此编写单元测试的地方

    using System;
    using System.Collections.Generic;
    using Xunit;
    
    namespace GradeBook.Tests
    {
        public class BookTests
        {
            [Fact]
            public void BookGradeIsValid()
            {
                var book = new Book("");           
                book.AddGrade(105);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

Som*_*ody 6

AddGrade()如果添加了无效成绩,我建议您修改您的方法以抛出异常:

public void AddGrade(double grade)
        {
            if (grade >= 0 && grade <= 100)
            {
                grades.Add(grade);               
            }
            else
            {
                throw new ArgumentException("grade must be between 0 and 100");
            }
        }
Run Code Online (Sandbox Code Playgroud)

你可以这样测试:

[Fact]
public void BookGradeIsValid()
{
      var book = new Book("");           
      Assert.Throws<ArgumentExeception>(() => book.AddGrade(101)); // should throw
      Assert.Throws<ArgumentExeception>(() => book.AddGrade(-1)); // should throw
      book.AddGrade(0); // should not throw
      book.AddGrade(100); // should not throw
}
Run Code Online (Sandbox Code Playgroud)

作为提示,不要使用 105 进行测试。直接在边界处使用值。如果你有一个错字,你写的if (grade >= 0 && grade <= 103)不是 100,你不会在你的测试中意识到它。

使用异常有几个优点。首先,您也可以Book在非控制台应用程序中使用该类。其次,如果出现问题,您可以进行自定义错误处理:

int grade = 300;
try
{
book.AddGrade(grade)
}
catch(ArgumentException)
{
   // so many possibilities: log to console or display a MessageBox or
   // send an e-mail to system admin or add grade with a default value or ...
}
Run Code Online (Sandbox Code Playgroud)

此外,您不能忽略异常。如果您添加一个带有无效值的等级,您的程序将停在那里,您不会想知道代码后面的 200 行,为什么缺少一个等级。

  • 我可以建议使用 [ArgumentOutOfRangeException](https://docs.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeException) 吗?另一个建议是使用[正确名称](/sf/answers/111583461/)将测试分成多个,或者至少使用一组参数(`InlineDataAttribute`?),因为单个测试应该执行单个*表演*。 (2认同)