2016-03-08 218 views
1

我发现了一个SonarQube 5.3场景,其中从Visual Studio代码覆盖率分析的代码覆盖率报告了不同的值。sonarqube中的代码覆盖率差异.net

这是一个使用MSTest框架的小型复制。

我无法确定我们正在做什么或者其中一个应用程序是否有错误。

对象被测试

[Serializable] 
public class Document : IEquatable<Document> 
{ 
    public long Id { get; set; } 
    public string Name { get; set; } 
    public long DocumentHandle { get; set; } 
    public long BatchId { get; set; } 
    public string BatchName { get; set; } 
    public string RepositoryName { get; set; } 
    public long DocumentTypeId { get; set; } 
    public string DocumentTypeName { get; set; } 
    public int SequenceNumber { get; set; } 
    public string LoanNumber { get; set; } 
    public bool IsJunked { get; set; } 
    public DateTime ArrivalDate { get; set; } 

    public bool Equals(Document other) 
    { 
     if (ReferenceEquals(other, null)) 
     { 
      return false; 
     } 

     if (Id != other.Id) 
     { 
      return false; 
     } 

     if (!string.Equals(Name, other.Name)) 
     { 
      return false; 
     } 

     if (DocumentHandle != other.DocumentHandle) 
     { 
      return false; 
     } 

     if (BatchId != other.BatchId) 
     { 
      return false; 
     } 

     if (!string.Equals(BatchName, other.BatchName)) 
     { 
      return false; 
     } 

     if (!string.Equals(RepositoryName, other.RepositoryName)) 
     { 
      return false; 
     } 

     if (DocumentTypeId != other.DocumentTypeId) 
     { 
      return false; 
     } 

     if (!string.Equals(DocumentTypeName, other.DocumentTypeName)) 
     { 
      return false; 
     } 

     if (SequenceNumber != other.SequenceNumber) 
     { 
      return false; 
     } 

     if (!string.Equals(LoanNumber, other.LoanNumber)) 
     { 
      return false; 
     } 

     if (IsJunked != other.IsJunked) 
     { 
      return false; 
     } 

     if (ArrivalDate != other.ArrivalDate) 
     { 
      return false; 
     } 

     return true; 
    } 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(null, obj)) 
     { 
      return false; 
     } 

     if (ReferenceEquals(this, obj)) 
     { 
      return true; 
     } 

     return Equals((Document) obj); 
    } 

    public static bool operator == (Document document1, Document document2) 
    { 
     return ReferenceEquals(document1, null) ? ReferenceEquals(document2, null) : document1.Equals(document2); 
    } 

    public static bool operator != (Document document1, Document document2) 
    { 
     return !(document1 == document2); 
    } 

    public override int GetHashCode() 
    { 
     // ReSharper disable once BaseObjectGetHashCodeCallInGetHashCode 
     // This was done to suppress the messages about needing to override GetHashCode 
     // Because this class has no ReadOnly properties there is no way to provide a better hashcode 
     return base.GetHashCode(); 
    } 
} 

该码具有以下测试:

[TestClass] 
[ExcludeFromCodeCoverage] 
public class DocumentTests 
{ 
    private Document defaultDocument; 
    private Document alteredDocument; 

    [TestInitialize] 
    public void Setup() 
    { 
     defaultDocument = new Document 
     { 
      Id = 1, 
      Name = "Growlithe", 
      DocumentHandle = 2, 
      BatchId = 3, 
      BatchName = "Vulpix", 
      RepositoryName = "Pancham", 
      DocumentTypeId = 4, 
      DocumentTypeName = "Skrelp", 
      SequenceNumber = 5, 
      LoanNumber = "Zorua", 
      IsJunked = true, 
      ArrivalDate = new DateTime(1, 1, 1) 
     }; 

     alteredDocument = new Document 
     { 
      Id = 1, 
      Name = "Growlithe", 
      DocumentHandle = 2, 
      BatchId = 3, 
      BatchName = "Vulpix", 
      RepositoryName = "Pancham", 
      DocumentTypeId = 4, 
      DocumentTypeName = "Skrelp", 
      SequenceNumber = 5, 
      LoanNumber = "Zorua", 
      IsJunked = true, 
      ArrivalDate = new DateTime(1, 1, 1) 
     }; 
    } 

    [TestMethod] 
    public void ToStringMethod_DocumentPOCO_ConvertObjectToString() 
    { 
     // Arrange 
     var expectedStringDocument = "Document" + Environment.NewLine + 
           "\tId: 101" + Environment.NewLine + 
           "\tName: TestName" + Environment.NewLine + 
           "\tDocumentHandle: 5000000" + Environment.NewLine + 
           "\tBatchId: 500000000" + Environment.NewLine + 
           "\tBatchName: TestBatchName" + Environment.NewLine + 
           "\tRepositoryName: TestRepositoryName" + Environment.NewLine + 
           "\tDocumentTypeId: 5000000" + Environment.NewLine + 
           "\tDocumentTypeName: TestDocumentTypeName" + Environment.NewLine + 
           "\tSequenceNumber: 101" + Environment.NewLine + 
           "\tLoanNumber: TestLoanNumber" + Environment.NewLine + 
           "\tIsJunked: False" + Environment.NewLine + 
           "\tArrivalDate: " + DateTime.Now + Environment.NewLine; 

     alteredDocument = new Document 
     { 
      Id = 101, 
      Name = "TestName", 
      DocumentHandle = 5000000, 
      BatchId = 500000000, 
      BatchName = "TestBatchName", 
      RepositoryName = "TestRepositoryName", 
      DocumentTypeId = 5000000, 
      DocumentTypeName = "TestDocumentTypeName", 
      SequenceNumber = 101, 
      LoanNumber = "TestLoanNumber", 
      IsJunked = false, 
      ArrivalDate = DateTime.Now 
     }; 

     // Act 
     var processedDocumentObj = StringUtility.StringUtility.ConvertToString(alteredDocument); 

     // Assert 
     Assert.IsTrue(processedDocumentObj.Equals(expectedStringDocument)); 
    } 

    [TestMethod] 
    public void EqualsReturnsTrueForEquivalentDocument() 
    { 
     Assert.IsTrue(defaultDocument.Equals(alteredDocument)); 
    } 

    [TestMethod] 
    public void EqualsReturnsFalseForNullDocument() 
    { 
     alteredDocument = null; 

     Assert.IsFalse(defaultDocument.Equals(alteredDocument)); 
    } 

    [TestMethod] 
    public void EqualsReturnsFalseForDifferentId() 
    { 
     alteredDocument.Id = 9; 

     Assert.IsFalse(defaultDocument.Equals(alteredDocument)); 
    } 

    [TestMethod] 
    public void EqualsReturnsFalseForDifferentName() 
    { 
     alteredDocument.Name = "Arcanine"; 

     Assert.IsFalse(defaultDocument.Equals(alteredDocument)); 
    } 

    [TestMethod] 
    public void EqualsReturnsFalseForDifferentDocumentHandle() 
    { 
     alteredDocument.DocumentHandle = 9; 

     Assert.IsFalse(defaultDocument.Equals(alteredDocument)); 
    } 

    [TestMethod] 
    public void EqualsReturnsFalseForDifferentBatchId() 
    { 
     alteredDocument.BatchId = 9; 

     Assert.IsFalse(defaultDocument.Equals(alteredDocument)); 
    } 

    [TestMethod] 
    public void EqualsReturnsFalseForDifferentBatchName() 
    { 
     alteredDocument.BatchName = "Ninetails"; 

     Assert.IsFalse(defaultDocument.Equals(alteredDocument)); 
    } 

    [TestMethod] 
    public void EqualsReturnsFalseForDifferentRepositoryName() 
    { 
     alteredDocument.RepositoryName = "Pangoro"; 

     Assert.IsFalse(defaultDocument.Equals(alteredDocument)); 
    } 

    [TestMethod] 
    public void EqualsReturnsFalseForDifferentDocumentTypeId() 
    { 
     alteredDocument.DocumentTypeId = 9; 

     Assert.IsFalse(defaultDocument.Equals(alteredDocument)); 
    } 

    [TestMethod] 
    public void EqualsReturnsFalseForDifferentDocumentTypeName() 
    { 
     alteredDocument.DocumentTypeName = "Dragalge"; 

     Assert.IsFalse(defaultDocument.Equals(alteredDocument)); 
    } 

    [TestMethod] 
    public void EqualsReturnsFalseForDifferentSequenceNumber() 
    { 
     alteredDocument.SequenceNumber = 9; 

     Assert.IsFalse(defaultDocument.Equals(alteredDocument)); 
    } 

    [TestMethod] 
    public void EqualsReturnsFalseForDifferentLoanNumber() 
    { 
     alteredDocument.LoanNumber = "Zoroark"; 

     Assert.IsFalse(defaultDocument.Equals(alteredDocument)); 
    } 

    [TestMethod] 
    public void EqualsReturnsFalseForDifferentIsJunked() 
    { 
     alteredDocument.IsJunked = false; 

     Assert.IsFalse(defaultDocument.Equals(alteredDocument)); 
    } 

    [TestMethod] 
    public void EqualsReturnsFalseForDifferentArrivalDate() 
    { 
     alteredDocument.ArrivalDate = new DateTime(2, 2, 2); 

     Assert.IsFalse(defaultDocument.Equals(alteredDocument)); 
    } 

    [TestMethod] 
    public void EqualsOperatorWorksForNonNullValues() 
    { 
     Assert.IsTrue(defaultDocument == alteredDocument); 
    } 

    [TestMethod] 
    public void NotEqualsOperatorWorksForNonNullValues() 
    { 
     alteredDocument = null; 

     Assert.IsTrue(defaultDocument != alteredDocument); 
    } 

    [TestMethod] 
    public void EqualsOperatorReturnsFalseForNullDotNonNull() 
    { 
     alteredDocument = null; 

     Assert.IsFalse(alteredDocument == defaultDocument); 
    } 

    [TestMethod] 
    public void EqualsOperatorReturnsFalseForNonNullDotNull() 
    { 
     alteredDocument = null; 

     Assert.IsFalse(defaultDocument == alteredDocument); 
    } 

    [TestMethod] 
    public void EqualsOperatorReturnsTrueForNullDotNull() 
    { 
     alteredDocument = null; 
     defaultDocument = null; 

     Assert.IsTrue(defaultDocument == alteredDocument); 
    } 
} 

Visual Studio中示出的百分比为:90.10%

SonarQube示出了百分比:40.00%


声纳不会出现在

if (ReferenceEquals(other, null)) 
{ 
    return false; 
} 
方法

后,考虑提前归还声明:public bool Equals(Document other)

我已经调试的测试,以验证线被击中。

+0

设置虚拟机在我自己的环境中重新制作它,远离工作,我无法重新制作它。我会把它带回给他们,我怀疑它是在该部署中的环境或配置。 – JABaran

回答

0

它可以是线/分支覆盖之间的差:白色间距 What is the difference between code coverage and line coverage in sonar

...或/行换行。

你可以找到SonarQube的指标描述页面在这里的公式:http://docs.sonarqube.org/display/SONAR/Metric+definitions#Metricdefinitions-Tests

覆盖率=(CT + CF + LC)/(2 * B + EL)

其中

CT - 分支机构其评估为“真”至少一次 CF - 覆盖线(lines_to_cover - - uncovered_lines)

乙 - 分支的总数评估为“假”至少一次 LC分支(2 * B = conditions_to_cover) EL - 可执行文件总数(lines_to_cover)