在Visual Studio 2015中从代码覆盖中排除自动属性
本文关键字:排除 属性 覆盖 Visual Studio 2015 代码 | 更新日期: 2023-09-27 18:10:50
我刚把一堆项目升级到VS2015/c# 6。
现在MSTest的代码覆盖率分析报告了一些自动属性没有被单元测试覆盖。在Visual Studio 2013中,情况并非如此,我怀疑这可能与c# 6中新的自动属性特性有关。
处理由此产生的所有误报反而违背了代码覆盖工具的目的,因为它实际上使识别缺乏测试覆盖的实际代码变得不可能。我们不想为所有的dto编写单元测试,而且我真的不想在整个项目中用ExcludeFromCodeCoverage
注释每一个自动属性。
我已经创建了一个工作的MCVE在https://github.com/iaingalloway/VisualStudioCodeCoverageIssue
- 在Visual Studio 2013 Premium或Ultimate中打开
- 单击测试->分析代码覆盖率->所有测试。
- 观察"代码覆盖结果"窗口报告0块"未覆盖"。
VisualStudio2013.sln
- Open
- 单击测试->分析代码覆盖率->所有测试。
- 观察"Code Coverage Results"窗口报告1个Block "Not Covered" (ExampleDto.Value的getter)
VisualStudio2015.sln
in Visual Studio 2015 Enterprise是否可以在Visual Studio 2015中配置内置的代码覆盖工具以忽略像Visual Studio 2013那样的自动属性?
作为一种解决方法,您可以在.runsettings文件中添加以下内容:-
<RunSettings>
<DataCollectionRunSettings>
<DataCollector ...>
<Configuration>
<CodeCoverage>
<Functions>
<Exclude>
<Function>.*get_.*</Function>
<Function>.*set_.*</Function>
</Exclude>
...
这不是一个很好的解决方案,但只要你不使用任何函数的名称中有"get_"或"set_",它应该得到你需要的行为
我不喜欢过滤所有get/set方法,特别是因为我有时编写需要测试的get和set逻辑。对我来说,对于相对简单的模型的基本覆盖,以下两个xUnit测试工作得很好:
public class ModelsGetSetTest
{
[ClassData(typeof(ModelTestDataGenerator))]
[Theory]
public void GettersGetWithoutError<T>(T model)
{
var properties =
typeof(T).GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
for (var i = 0; i < properties.Length; i++)
{
var prop = properties[i];
if (prop.GetGetMethod(true) != null)
prop.GetValue(model);
}
}
[ClassData(typeof(ModelTestDataGenerator))]
[Theory]
public void SettersSetWithoutError<T>(T model)
{
var properties =
typeof(T).GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
for (var i = 0; i < properties.Length; i++)
{
var prop = properties[i];
if (prop.GetSetMethod(true) != null)
prop.SetValue(model, null);
}
}
public class ModelTestDataGenerator : IEnumerable<object[]>
{
private readonly List<object[]> _data = new List<object[]>();
public ModelTestDataGenerator()
{
var assembly = typeof(Program).Assembly;
var nsprefix = $"{typeof(Program).Namespace}.{nameof(Models)}";
var modelTypes = assembly.GetTypes()
.Where(t => t.IsClass && !t.IsGenericType) // can instantiate without much hubbub
.Where(t => t.Namespace.StartsWith(nsprefix)) // is a model
.Where(t => t.GetConstructor(Type.EmptyTypes) != null) // has parameterless constructor
.ToList();
foreach (var modelType in modelTypes) _data.Add(new[] {Activator.CreateInstance(modelType)});
}
public IEnumerator<object[]> GetEnumerator()
{
return _data.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
更新于2020-03-18:此版本使用反射来查找特定命名空间下的模型。
我认为[ExcludeFromCodeCoverage]
是你唯一的选择。这只是你必须做的一次性的事情。就我个人而言,我确实会在属性getter/setter上编写单元测试,特别是在WPF中,我想确保属性更改通知发生。