按时 Visual Studio 的代码覆盖率
Code Coverage in Visual Studio on Time
我在 Visual Studio 2013 年编写单元测试,但在我的代码覆盖率分析中遇到了问题。语言是 C# 并使用默认 Microsoft.VisualStudio.TestTools.UnitTesting.
if (exsistingNode.NodeState > NodeState.Edit)
{
if (existingNode.NodeName != updatedNode.NodeName)
{
throw m_Diagnostics.ThrowCannotUpdateAfterEditState(subject, existingNode.NodeId, "NodeName");
}
if (existingNode.StartDate != updatedNode.StartDate)
{
throw m_Diagnostics.ThrowCannotUpdateAfterEditState(subject, existingNode.NodeId, "StartDate");
}
if (existingNode.Description != updatedNode.Description)
{
throw m_Diagnostics.ThrowCannotUpdateAfterEditState(subject, existingNode.NodeId, "Description");
}
}
我已经为每个 if 语句做了单元测试。我的第一个单元测试是成功的,它通过了所有这些并且没有抛出任何错误,然后我有三个单独的单元测试来测试每个 if 语句并抛出错误。我的问题是代码分析显示语句:
if (existingNode.StartDate != updatedNode.StartDate)
只进行了部分测试,我不明白为什么。这是因为它处理时间吗?
以下代码也是如此,其中抛出被代码覆盖,但所有 if 语句都被代码部分覆盖。
if (updatedNode.StartDate != existingNode.StartDate)
{
if (updatedNode.StartDate.HasValue && updatedNode.StartDate < DateTime.Now)
{
throw m_Diagnostics.ThrowUpdateNodeException(subject, existingNode.NodeId, new InvalidOperationException("Cannot set the start date less than now."));
}
if (updatedNode.StartDate.HasValue && updatedNode.EndDate.HasValue && updatedNode.EndDate < updatedNode.StartDate)
{
throw m_Diagnostics.ThrowUpdateNodeException(subject, existingNode.NodeId, new InvalidOperationException("Cannot set the end date less than the start date."));
}
}
if (updatedNode.EndDate != existingNode.EndDate)
{
if (updatedNode.EndDate.HasValue && updatedNode.EndDate < DateTime.Now)
{
throw m_Diagnostics.ThrowUpdateNodeException(subject, existingNode.NodeId, new InvalidOperationException("Cannot set the end date lessthan now."));
}
有人要求提供单元测试的一些示例。以下是与第一种情况有关的两个。如果您在其他情况下需要它们,请告诉我。
[TestMethod] // Start Date Test that is only Partially covered
[ExpectedException(typeof(Exception))]
public void ChangeStartDate() // Unit Test where the Start Date is changed when not in Edit Mode
{
//Arrange
Node nodeToUpdate = new Node
{
NodeName = "nodeName",
StartDate = DateTime.Now.AddDays(1),
NodeState = NodeState.Open
};
collectionNode.Add(nodeToUpdate);
Node updatedNode = new Node
{
NodeName = "nodeName",
StartDate = DateTime.Now.AddDays(2),
NodeState = NodeState.Open
};
INodeStore stubNodeStore = new CENSORED.StubINodeStore
{
GetNodeString = (NodeId) =>
{
return nodeToUpdate;
}
};
server.NodeStoreStubs = stubNodeStore;
INodePrivilegeStore stubNodePrivilegeStore = new CENSORED.StubINodePrivilegeStore
{
GetPrivilegeStringString = (NodeId, subject) =>
{
return new NodePrivilege
{
Permissions = NodePermissions.Administrator
};
}
};
server.NodePrivilegeStoreStubs = stubNodePrivilegeStore;
m_NodeManager = ThrowHelper.GetServiceOrThrow<INodeManager>(server);
//Act
m_NodeManager.UpdateNode(updatedNode);
//Assert
}
[TestMethod] // Unit Test that is fully covered
[ExpectedException(typeof(Exception))]
public void ChangeStartDate() // Unit Test where the Start Date is changed when not in Edit Mode
{
//Arrange
Node nodeToUpdate = new Node
{
NodeName = "nodeName",
StartDate = DateTime.Now.AddDays(1),
Description = "description,
NodeState = NodeState.Open
};
collectionNode.Add(nodeToUpdate);
Node updatedNode = new Node
{
NodeName = "nodeName",
StartDate = DateTime.Now.AddDays(1),
Description = "updatedDescription"
NodeState = NodeState.Open
};
INodeStore stubNodeStore = new CENSORED.StubINodeStore
{
GetNodeString = (NodeId) =>
{
return nodeToUpdate;
}
};
server.NodeStoreStubs = stubNodeStore;
INodePrivilegeStore stubNodePrivilegeStore = new CENSORED.StubINodePrivilegeStore
{
GetPrivilegeStringString = (NodeId, subject) =>
{
return new NodePrivilege
{
Permissions = NodePermissions.Administrator
};
}
};
server.NodePrivilegeStoreStubs = stubNodePrivilegeStore;
m_NodeManager = ThrowHelper.GetServiceOrThrow<INodeManager>(server);
//Act
m_NodeManager.UpdateNode(updatedNode);
//Assert
}
在进行 'if' 测试时,您应该考虑所有组合的所有可能情况。
如果您不确定 if 的哪一部分未被正确测试,请尝试将它们分开,请查看哪个 'if' 语句未针对两个值进行测试。
public bool IsTimeBeforeNow(Nullable<DateTime> time)
{
if (time.HasValue && time.Value < DateTime.Now)
return true;
return false;
}
[TestMethod]
public void TestIsTimeBeforeNow()
{
//test time.HasValue with null
Assert.AreEqual(false, this.IsTimeBeforeNow(null));
//test time.HasValue with true
//and test time.Value > DateTime.Now
Assert.AreEqual(false, this.IsTimeBeforeNow(DateTime.Now.AddDays(1)));
//test time.HasValue with true
//and test time.Value < DateTime.Now
Assert.AreEqual(true, this.IsTimeBeforeNow(DateTime.Now.AddDays(-1)));
}
关键是测试每条逻辑路径。
当你有一个 "if" 语句时,你必须同时测试 if == true 和 if == false 场景,以获得完整的代码覆盖率。
当您有一个 "switch" 语句时,您必须测试所有可能的情况,包括默认情况。
我在 Visual Studio 2013 年编写单元测试,但在我的代码覆盖率分析中遇到了问题。语言是 C# 并使用默认 Microsoft.VisualStudio.TestTools.UnitTesting.
if (exsistingNode.NodeState > NodeState.Edit)
{
if (existingNode.NodeName != updatedNode.NodeName)
{
throw m_Diagnostics.ThrowCannotUpdateAfterEditState(subject, existingNode.NodeId, "NodeName");
}
if (existingNode.StartDate != updatedNode.StartDate)
{
throw m_Diagnostics.ThrowCannotUpdateAfterEditState(subject, existingNode.NodeId, "StartDate");
}
if (existingNode.Description != updatedNode.Description)
{
throw m_Diagnostics.ThrowCannotUpdateAfterEditState(subject, existingNode.NodeId, "Description");
}
}
我已经为每个 if 语句做了单元测试。我的第一个单元测试是成功的,它通过了所有这些并且没有抛出任何错误,然后我有三个单独的单元测试来测试每个 if 语句并抛出错误。我的问题是代码分析显示语句:
if (existingNode.StartDate != updatedNode.StartDate)
只进行了部分测试,我不明白为什么。这是因为它处理时间吗?
以下代码也是如此,其中抛出被代码覆盖,但所有 if 语句都被代码部分覆盖。
if (updatedNode.StartDate != existingNode.StartDate)
{
if (updatedNode.StartDate.HasValue && updatedNode.StartDate < DateTime.Now)
{
throw m_Diagnostics.ThrowUpdateNodeException(subject, existingNode.NodeId, new InvalidOperationException("Cannot set the start date less than now."));
}
if (updatedNode.StartDate.HasValue && updatedNode.EndDate.HasValue && updatedNode.EndDate < updatedNode.StartDate)
{
throw m_Diagnostics.ThrowUpdateNodeException(subject, existingNode.NodeId, new InvalidOperationException("Cannot set the end date less than the start date."));
}
}
if (updatedNode.EndDate != existingNode.EndDate)
{
if (updatedNode.EndDate.HasValue && updatedNode.EndDate < DateTime.Now)
{
throw m_Diagnostics.ThrowUpdateNodeException(subject, existingNode.NodeId, new InvalidOperationException("Cannot set the end date lessthan now."));
}
有人要求提供单元测试的一些示例。以下是与第一种情况有关的两个。如果您在其他情况下需要它们,请告诉我。
[TestMethod] // Start Date Test that is only Partially covered
[ExpectedException(typeof(Exception))]
public void ChangeStartDate() // Unit Test where the Start Date is changed when not in Edit Mode
{
//Arrange
Node nodeToUpdate = new Node
{
NodeName = "nodeName",
StartDate = DateTime.Now.AddDays(1),
NodeState = NodeState.Open
};
collectionNode.Add(nodeToUpdate);
Node updatedNode = new Node
{
NodeName = "nodeName",
StartDate = DateTime.Now.AddDays(2),
NodeState = NodeState.Open
};
INodeStore stubNodeStore = new CENSORED.StubINodeStore
{
GetNodeString = (NodeId) =>
{
return nodeToUpdate;
}
};
server.NodeStoreStubs = stubNodeStore;
INodePrivilegeStore stubNodePrivilegeStore = new CENSORED.StubINodePrivilegeStore
{
GetPrivilegeStringString = (NodeId, subject) =>
{
return new NodePrivilege
{
Permissions = NodePermissions.Administrator
};
}
};
server.NodePrivilegeStoreStubs = stubNodePrivilegeStore;
m_NodeManager = ThrowHelper.GetServiceOrThrow<INodeManager>(server);
//Act
m_NodeManager.UpdateNode(updatedNode);
//Assert
}
[TestMethod] // Unit Test that is fully covered
[ExpectedException(typeof(Exception))]
public void ChangeStartDate() // Unit Test where the Start Date is changed when not in Edit Mode
{
//Arrange
Node nodeToUpdate = new Node
{
NodeName = "nodeName",
StartDate = DateTime.Now.AddDays(1),
Description = "description,
NodeState = NodeState.Open
};
collectionNode.Add(nodeToUpdate);
Node updatedNode = new Node
{
NodeName = "nodeName",
StartDate = DateTime.Now.AddDays(1),
Description = "updatedDescription"
NodeState = NodeState.Open
};
INodeStore stubNodeStore = new CENSORED.StubINodeStore
{
GetNodeString = (NodeId) =>
{
return nodeToUpdate;
}
};
server.NodeStoreStubs = stubNodeStore;
INodePrivilegeStore stubNodePrivilegeStore = new CENSORED.StubINodePrivilegeStore
{
GetPrivilegeStringString = (NodeId, subject) =>
{
return new NodePrivilege
{
Permissions = NodePermissions.Administrator
};
}
};
server.NodePrivilegeStoreStubs = stubNodePrivilegeStore;
m_NodeManager = ThrowHelper.GetServiceOrThrow<INodeManager>(server);
//Act
m_NodeManager.UpdateNode(updatedNode);
//Assert
}
在进行 'if' 测试时,您应该考虑所有组合的所有可能情况。 如果您不确定 if 的哪一部分未被正确测试,请尝试将它们分开,请查看哪个 'if' 语句未针对两个值进行测试。
public bool IsTimeBeforeNow(Nullable<DateTime> time)
{
if (time.HasValue && time.Value < DateTime.Now)
return true;
return false;
}
[TestMethod]
public void TestIsTimeBeforeNow()
{
//test time.HasValue with null
Assert.AreEqual(false, this.IsTimeBeforeNow(null));
//test time.HasValue with true
//and test time.Value > DateTime.Now
Assert.AreEqual(false, this.IsTimeBeforeNow(DateTime.Now.AddDays(1)));
//test time.HasValue with true
//and test time.Value < DateTime.Now
Assert.AreEqual(true, this.IsTimeBeforeNow(DateTime.Now.AddDays(-1)));
}
关键是测试每条逻辑路径。
当你有一个 "if" 语句时,你必须同时测试 if == true 和 if == false 场景,以获得完整的代码覆盖率。
当您有一个 "switch" 语句时,您必须测试所有可能的情况,包括默认情况。