簡體   English   中英

從 Visual Studio 2015 中的代碼覆蓋率中排除自動屬性

[英]Exclude auto properties from Code Coverage in Visual Studio 2015

我剛剛將一堆項目升級到 VS2015/C#6。

現在,MSTest 的代碼覆蓋率分析報告說單元測試未涵蓋某些自動屬性。 在 Visual Studio 2013 中情況並非如此,我懷疑這可能與 C#6 中的新自動屬性功能有關。

處理由此產生的所有誤報反而違背了代碼覆蓋工具的目的,因為它實際上無法識別缺乏測試覆蓋的實際代碼。 我們不想為我們所有的 DTO 編寫單元測試,而且我真的不想完成項目,用ExcludeFromCodeCoverage注釋每個自動屬性。

我在https://github.com/iaingalloway/VisualStudioCodeCoverageIssue創建了一個有效的 MCVE


  • 在 Visual Studio 2013 Premium 或 Ultimate 中打開VisualStudio2013.sln
  • 單擊測試 -> 分析代碼覆蓋率 -> 所有測試。
  • 觀察“代碼覆蓋率結果”窗口報告 0 塊“未覆蓋”。

  • 在 Visual Studio 2015 Enterprise 中打開VisualStudio2015.sln
  • 單擊測試 -> 分析代碼覆蓋率 -> 所有測試。
  • 觀察“代碼覆蓋率結果”窗口報告 1 塊“未覆蓋”(ExampleDto.Value 的 getter)

是否可以在 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 年 3 月 18 日更新:此版本使用反射在特定命名空間下查找模型。

我認為[ExcludeFromCodeCoverage]是您唯一的選擇。 這只是你必須要做的一次性事情。 我個人對屬性 getter/setter 編寫單元測試,尤其是在 WPF 中,我想確保屬性更改通知發生。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM