起源是,用MemberData进行封装的Test方法,在Visual Studio 的Test Explorer中只显示为1个。本来,这个显示问题没啥问题,问题是,当你其中一个测试用例出错,而你又想进行Debug的时候,在Test Explorer中运行该方法,实际上会遍历所有的调用,是的Debug过程异常麻烦。
于是去找Github, StackOverflow, 果不其然,c# - MemberData tests show up as one test instead of many - Stack Overflow,有人遇到了同样的问题。
遵循上述Question的解决方案中的做法,实现IXunitSerializable,然而,得到的其实,Visual Studio的Test Explorer再也无法显示了。
示例代码:
public DayOfWeek Dow { get; private set; }
public List<UserHabitRecord> RecordList { get; private set; }
public int CompleteCondition { get; private set; }
public int RecordCount { get; private set; }
public List<DateTime> TargetRuleDateList { get; private set; }
public Guid InstanceID { get; private set; }
public UserHabitRecordsControllerTestData_WeekNoOfCount()
{
this.RecordList = new List<UserHabitRecord>();
this.TargetRuleDateList = new List<DateTime>();
this.InstanceID = Guid.NewGuid();
}
public UserHabitRecordsControllerTestData_WeekNoOfCount(DayOfWeek dow,
List<UserHabitRecord> records, int completeCondition, int recordCount,
List<DateTime> arTargetRuleDate) : this()
{
this.Dow = dow;
this.RecordList.AddRange(records);
this.CompleteCondition = completeCondition;
this.RecordCount = recordCount;
this.TargetRuleDateList.AddRange(arTargetRuleDate);
}
public void Deserialize(IXunitSerializationInfo info)
{
Dow = info.GetValue<DayOfWeek>("Dow");
RecordList = info.GetValue<List<UserHabitRecord>>("RecordList");
CompleteCondition = info.GetValue<int>("CompleteCondition");
RecordCount = info.GetValue<int>("RecordCount");
TargetRuleDateList = info.GetValue<List<DateTime>>("TargetRuleDateList");
InstanceID = Guid.Parse(info.GetValue<String>(nameof(InstanceID)));
}
public void Serialize(IXunitSerializationInfo info)
{
info.AddValue(nameof(Dow), Dow, typeof(DayOfWeek));
info.AddValue("RecordList", RecordList, typeof(List<UserHabitRecord>));
info.AddValue("CompleteCondition", CompleteCondition, typeof(int));
info.AddValue("RecordCount", RecordCount, typeof(int));
info.AddValue("TargetRuleDateList", TargetRuleDateList, typeof(List<DateTime>));
info.AddValue(nameof(InstanceID), InstanceID.ToString("N"), typeof(String));
}
不死心,用dotnet CLI的方法尝试了一下,原来是所有的测试都无法Discover了:
dotnet test -t
上述命令无法完成,只能Ctrl+C强制退出。
再去xUnit上去翻文档,再去Github, Stackoverflow上翻Issue,再去Google上查找IXunitSerializable的示例代码,但是没有结果。
又去下载了最新的Visual Studio 2022,问题依旧。
甚至都准备换MSTest或者NUnit框架了,只是看看之前写的那么多Test Cases,想想这种换Test Framework的苦力获,只得作罢。
最终狠下心来,彻底搞明白这个问题然后彻底解决之。于是突然想到,这个过程应该是卡在Serialization的方法里面,应该是List
于是操刀动手:
public DayOfWeek Dow { get; set; }
public List<UserHabitRecord> RecordList { get; set; }
public int CompleteCondition { get; set; }
public int RecordCount { get; set; }
public List<DateTime> TargetRuleDateList { get; set; }
public void Deserialize(IXunitSerializationInfo info)
{
String val = info.GetValue<String>("Value");
UserHabitRecordsControllerTestData_WeekNoOfCount other = JsonSerializer.Deserialize<UserHabitRecordsControllerTestData_WeekNoOfCount>(val);
// CaseID = other.CaseID;
Dow = other.Dow;
CompleteCondition = other.CompleteCondition;
RecordCount = other.RecordCount;
if (other.RecordList.Count > 0)
RecordList.AddRange(other.RecordList);
if (other.TargetRuleDateList.Count > 0)
TargetRuleDateList.AddRange(other.TargetRuleDateList);
}
public void Serialize(IXunitSerializationInfo info)
{
String val = JsonSerializer.Serialize(this);
info.AddValue("Value", val, typeof(String));
}
BINGO!!!
踏破铁鞋无觅处啊,看到Test Explorer中那跳动数字,差点从椅子上跳起来。
中间还有个小插曲,虽然Test Explorer显示正确,但是测试始终失败。打了个断点一瞧,Deserialize的结果一直为空。原因是Property设置为了private set了:
public DayOfWeek Dow { get; private set; }
public List<UserHabitRecord> RecordList { get; private set; }
public int CompleteCondition { get; private set; }
public int RecordCount { get; private set; }
public List<DateTime> TargetRuleDateList { get; private set; }
收工。
是为之记。 Alva Chien 2021.11.15