Skip to main content
added 795 characters in body
Source Link
Ixrec
  • 27.7k
  • 15
  • 84
  • 87

That depends largelyto some extent on how you choose to interpret those two terms, but the answer is probably that both are possible.


First the easy half. I believe thatoff, most reasonable definitions of the two terms make it very easy to get path and branch coverage without condition coverage. For example:

function isPositive(x) {
    return x > 0;
}

Testing isPositive with only one value of x will get you path and branch coverage but not condition coverage.


GettingSimilarly, it's also very easy to get condition and branch coverage withoutwhile failing to get path coverage.

function printPositivities(x, y) {
    if(x > 0) {
        std::cout << "x is positive";
    } else {
        std::cout << "x is non-positive";
    }
    if(y > 0) {
        std::cout << "y is positive";
    } else {
        std::cout << "y is non-positive";
    }
}

If you test this once with positive numbers, then again with non-positive numbers, you will achieve condition coverage (both if conditions turn out true and false) and branch coverage (since all four std::cout statements get executed) but not path coverage (since you miss the paths where one is significantly harderpositive and the other isn't).


The more interesting question (which you didn't ask, sincebut for some reason I thought you have to come up withdid) is whether you can get condition coverage without branch coverage.

To do that you need a reason for the program to branch that does not qualify as a "condition". In many languages, the x in if(x) doesn't have to be a boolean, but in most cases that is probably more of an uninteresting loophole than a genuine answer since x will still have to be "truthy" or "falsy".

  The most interesting non-loophole cases of "non-boolean branching" that I can come up with are:

  1. catch blocks. In most (all?) languages with exceptions, a catch block never gets executed unless an exception actually gets thrown, so it's easy to write code with perfect condition coverage that never throws any exceptions, and then add a try/catch block even though there's nothing there to catch.

  2. Go's select syntax on channels:

    select { case msg1 := <-channel1: fmt.Println("received", msg1) case msg2 := <-channel2: fmt.Println("received", msg2) }

This causes the program to wait until either channel1 or channel2 has data that can be received, then it receives that data and executes the block of code corresponding to the channel that it received from. Note that this actually blocks execution for an arbitrary length of time, rather than calling channel1.isReady() or something, which is why I believe this counts. If you simply ensure that channel1 always has data to receive and channel2 doesn't, you have a branch coverage failure.

That depends largely on how you choose to interpret those two terms, but the answer is probably that both are possible.


First the easy half. I believe that most reasonable definitions of the two terms make it very easy to get branch coverage without condition coverage. For example:

function isPositive(x) {
    return x > 0;
}

Testing isPositive with only one value of x will get you branch coverage but not condition coverage.


Getting condition coverage without branch coverage is significantly harder, since you have to come up with a reason for the program to branch that does not qualify as a "condition". In many languages, the x in if(x) doesn't have to be a boolean, but in most cases that is probably more of an uninteresting loophole than a genuine answer since x will still have to be "truthy" or "falsy".

  The most interesting non-loophole cases of "non-boolean branching" that I can come up with are:

  1. catch blocks. In most (all?) languages with exceptions, a catch block never gets executed unless an exception actually gets thrown, so it's easy to write code with perfect condition coverage that never throws any exceptions, and then add a try/catch block even though there's nothing there to catch.

  2. Go's select syntax on channels:

    select { case msg1 := <-channel1: fmt.Println("received", msg1) case msg2 := <-channel2: fmt.Println("received", msg2) }

This causes the program to wait until either channel1 or channel2 has data that can be received, then it receives that data and executes the block of code corresponding to the channel that it received from. Note that this actually blocks execution for an arbitrary length of time, rather than calling channel1.isReady() or something, which is why I believe this counts. If you simply ensure that channel1 always has data to receive and channel2 doesn't, you have a branch coverage failure.

That depends to some extent on how you choose to interpret those two terms, but the answer is probably that both are possible.


First off, most reasonable definitions of the two terms make it very easy to get path and branch coverage without condition coverage. For example:

function isPositive(x) {
    return x > 0;
}

Testing isPositive with only one value of x will get you path and branch coverage but not condition coverage.


Similarly, it's also very easy to get condition and branch coverage while failing to get path coverage.

function printPositivities(x, y) {
    if(x > 0) {
        std::cout << "x is positive";
    } else {
        std::cout << "x is non-positive";
    }
    if(y > 0) {
        std::cout << "y is positive";
    } else {
        std::cout << "y is non-positive";
    }
}

If you test this once with positive numbers, then again with non-positive numbers, you will achieve condition coverage (both if conditions turn out true and false) and branch coverage (since all four std::cout statements get executed) but not path coverage (since you miss the paths where one is positive and the other isn't).


The more interesting question (which you didn't ask, but for some reason I thought you did) is whether you can get condition coverage without branch coverage.

To do that you need a reason for the program to branch that does not qualify as a "condition". In many languages, the x in if(x) doesn't have to be a boolean, but in most cases that is probably more of an uninteresting loophole than a genuine answer since x will still have to be "truthy" or "falsy". The most interesting non-loophole cases of "non-boolean branching" that I can come up with are:

  1. catch blocks. In most (all?) languages with exceptions, a catch block never gets executed unless an exception actually gets thrown, so it's easy to write code with perfect condition coverage that never throws any exceptions, and then add a try/catch block even though there's nothing there to catch.

  2. Go's select syntax on channels:

    select { case msg1 := <-channel1: fmt.Println("received", msg1) case msg2 := <-channel2: fmt.Println("received", msg2) }

This causes the program to wait until either channel1 or channel2 has data that can be received, then it receives that data and executes the block of code corresponding to the channel that it received from. Note that this actually blocks execution for an arbitrary length of time, rather than calling channel1.isReady() or something, which is why I believe this counts. If you simply ensure that channel1 always has data to receive and channel2 doesn't, you have a branch coverage failure.

Source Link
Ixrec
  • 27.7k
  • 15
  • 84
  • 87

That depends largely on how you choose to interpret those two terms, but the answer is probably that both are possible.


First the easy half. I believe that most reasonable definitions of the two terms make it very easy to get branch coverage without condition coverage. For example:

function isPositive(x) {
    return x > 0;
}

Testing isPositive with only one value of x will get you branch coverage but not condition coverage.


Getting condition coverage without branch coverage is significantly harder, since you have to come up with a reason for the program to branch that does not qualify as a "condition". In many languages, the x in if(x) doesn't have to be a boolean, but in most cases that is probably more of an uninteresting loophole than a genuine answer since x will still have to be "truthy" or "falsy".

The most interesting non-loophole cases of "non-boolean branching" that I can come up with are:

  1. catch blocks. In most (all?) languages with exceptions, a catch block never gets executed unless an exception actually gets thrown, so it's easy to write code with perfect condition coverage that never throws any exceptions, and then add a try/catch block even though there's nothing there to catch.

  2. Go's select syntax on channels:

    select { case msg1 := <-channel1: fmt.Println("received", msg1) case msg2 := <-channel2: fmt.Println("received", msg2) }

This causes the program to wait until either channel1 or channel2 has data that can be received, then it receives that data and executes the block of code corresponding to the channel that it received from. Note that this actually blocks execution for an arbitrary length of time, rather than calling channel1.isReady() or something, which is why I believe this counts. If you simply ensure that channel1 always has data to receive and channel2 doesn't, you have a branch coverage failure.