c# - 集合上的单元测试理论 xUnit
问题描述
原始问题
假设我有一个类方法GetAge(DateTime dateOfBirth)
,我想测试出来的年龄是否正确。为此,我创建了一个名为的辅助方法GenerateDateOfBirth(int age)
,该方法返回应产生年龄的出生日期age
。
但是,我不知道我的GenerateDateOfBirth
方法是否有效,因此我想批量测试要输入的年龄集合GenerateDateOfBirth
,其中每个生成的出生日期在输入时都应该产生原始年龄GetAge
,类似于:
[Fact]
public void CrossTestGetAgeAndGenerateDateOfBirth()
{
var ages = new List<int>(); // A reasonably large list of possible ages
var rng = new Random();
for (int i = 0; i < 1_000_000; i++)
{
ages.Add(rng.Next(0, 1000)); // Arbitrary upper bound on a person's age
}
foreach (var realAge in ages)
{
var dateOfBirth = GenerateDateOfBirth(realAge);
var calculatedAge = GetAge(dateOfBirth);
Assert.Equal(realAge, calculatedAge); // If false, at least one of the methods is bugged
}
}
我已经看到 xUnit 允许通过使用 和 等属性对数据进行测试InlineData
,MemberData
所以我想知道是否可以生成一个整数列表,然后对所有“年龄”值进行数据驱动测试,如下所示:
public List<int> Ages { get; set; } = GetAges(0, 1000, 1_000_000); // Same arbitrary bounds as above
public List<int> GetAges(int minAge, int maxAge, int count)
{
var ages = new List<int>();
var rng = new Random();
for (int i = 0; i < count; i++)
{
ages.Add(rng.Next(minAge, maxAge));
}
return ages;
}
[Theory]
[/* something with Ages */]
public void AgeFromDateOfBirthFromAge(/* what goes here? */)
{
var randomDateOfBirth = GenerateDateOfBirth(age); // Where age comes from Ages
var calculatedAge = GetAge(randomDateOfBirth);
Assert.Equal(age, calculatedAge);
}
这看起来更简洁易读,而且它仍然做同样的事情。我的目标(在我可以编写实际的单元测试之前)是通过用大量随机数据轰炸这两种方法来嗅出任何可能的边缘情况。一旦其中一种方法似乎运行良好,理想情况下,我可以使用它来修复另一种方法,然后对可能保留的(希望)少数边缘情况进行最终审查。有没有办法做到这一点?
两种方法的当前实现
获取年龄的方法
public int GetAge(DateTime dob)
{
var now = DateTime.Now;
// Time difference up to the day
int deltaDays = now.Day - dob.Day;
int deltaMonths = now.Month - dob.Month;
int deltaYears = now.Year - dob.Year;
int age = (deltaDays + 100 * deltaMonths + 10000 * deltaYears) / 10000;
// Check if time of day has also been reached
var timeNotReached = now.TimeOfDay.Ticks < dob.TimeOfDay.Ticks;
return (deltaDays == 0 && deltaMonths == 0 && timeNotReached) ? age - 1 : age;
}
生成出生日期的方法
public DateTime GenerateDateOfBirth(int age = 18)
{
var rng = new Random();
var now = DateTime.Now;
// Get allowed values for birth date
var maxMonth = now.Month + 1;
var maxDay = now.Day + 1;
var maxHour = now.Hour + 1;
var maxMinute = now.Minute + 1;
var maxSecond = now.Second + 1;
var maxMillisecond = now.Millisecond;
// Choose random allowed values
var birthYear = now.Year - age;
var birthMonth = rng.Next(1, maxMonth);
var birthDay = birthMonth != now.Month ? rng.Next(1, DateTime.DaysInMonth(birthYear, birthMonth) + 1) : rng.Next(1, maxDay);
var birthHour = rng.Next(1, maxHour);
var birthMinute = rng.Next(1, maxMinute);
var birthSecond = rng.Next(1, maxSecond);
var birthMillisecond = rng.Next(maxMillisecond);
var dateOfBirth = new DateTime(
birthYear,
birthMonth,
birthDay,
birthHour,
birthMinute,
birthSecond,
birthMillisecond
);
return dateOfBirth;
}
解决方案
推荐阅读
- javascript - 返回导出模块的最佳方式
- vue.js - Vuejs - 如何使用 v-for 获取数组中的所有唯一值(删除重复项)
- scala - Scala 不能转换类型 Publisher[Publisher[_ <: T]] 不能应用于 (Flux[Flux[String]]
- django - 如何使用 Keycloak Token 获取权限列表
- python - 如何取消制表符(-1 制表符)?
- kubernetes - 如果命令返回码非零,如何终止 kubernetes 作业
- excel - VBA 帮助 - 通过调用函数运行 3 个宏的脚本不会运行所有宏
- rest - 在 Oracle APEX AJAX On demand 过程中调用 POST Web 服务
- spring - Spring boot(数据 jpa)我无法将 eumn 值保存在数据库中
- java - 为什么不安全的双重检查锁定可以返回空值?