简体   繁体   中英

Code Coverage in Visual Studio on Time

I am writing unit Tests in Visual Studio 2013 and having trouble on my code coverage analysis. Language is C# and using the default 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");
    }
}

I have done a unit test for each if statement. My first unit test which is a success goes through all of them and throws no error and then I have three separate Unit Tests that test each if statement and throw an error. My problem is that Code Analysis shows the statement:

if (existingNode.StartDate != updatedNode.StartDate)

as only partially tested and I can't under stand why. Is this because it deals with time?

The same is true in the following code where the throws are code covered but all the if statements are code partially covered.

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."));
    }

Someone asked for some examples of the Unit Tests. Follows are two that have to do with the first case. If you need them for the other cases let me know.

[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
}

When doing your 'if' tests you should think of all the cases possible with all combinations. If you are not sure which part of the if is not correctly tested try to separate them, see which 'if' statement is not tested for both values.

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)));
}

The key is testing every logic pathway.

When you have an "if" statement, you must test both the if == true and the if == false scenarios, to have full code coverage.

When you have a "switch" statement, you must test every possible case, including the default.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM