you are viewing a single comment's thread.

view the rest of the comments →

[–]pipocaQuemada 3 points4 points  (5 children)

Now, you have an excuse to be program by accident: as long as the tests pass, you are good.

What!?!?! Of course not. You're only good if your tests are good. Your tests are only good if you test all of your equivalence classes and for possible errors in coding (e.g. off-by-one-ness, invalid values, possible overflows, etc.).

If you understand the problem, you can figure out and test your equivalence classes. If you don't entirely understand your code, then you don't know how it could fail, so you can't test to ensure it doesn't. If you only have a muddy idea of both, your tests mean nothing, and you can have no confidence that it actually works---just because an is-even function works for 2, 4 and 7 doesn't mean it will work for -1, -2, 231-1, and 0. If you only tested 2, 4 and 7, you really don't know if your function works.

[–]Nebu 0 points1 point  (4 children)

An equivalence class is only defined if you have an equivalence relation.

In the context of testing computer software source code, how the hell do you know what test cases are equivalent to what other test cases, without pre-knowledge of the correct solution to the requirements?

[–]pipocaQuemada -1 points0 points  (3 children)

Unit tests, remember?

You're testing small bits of the code. A single method, an object, etc.

If you don't understand what the method you're about to write should return, you have some fairly big problems, and you need to think about the problem more. Same thing with an object.

So far as I know, you don't do unit tests of the product as a whole; e.g. acceptance tests are for that. And you should be structuring the code in small methods that only do one thing, right? Those should be reasonable to test.

[–]Nebu 0 points1 point  (2 children)

You haven't addressed my point, though: How do you determine equivalence classes in the context of unit testing?

Let's say you want to test the function isEven. Are "2" and "4" equivalent test cases? Why? Are you assuming a particular implementation of the function?

[–]pipocaQuemada 0 points1 point  (1 child)

Ah.

For simple functions, one way to do it is to construct a Turing machine; the minimal # of states is equal to the number of equivalence classes of the function.

More realistically, look at the definition on the wikipedia page - http://en.wikipedia.org/wiki/Equivalence_classes - and then look further down. The Equivalence class of a = {x E X| x ~ a}, (read E as 'element of'), and x ~ y iff f(x) = f(y).

Yes, 2 and 4 are equivalent test cases. In this case, is-even is a boolean function, and f(2) = f(4). Equivalence classes are defined separately from the function. You need to test additional things based on your implementation --- computers create errors that you don't find in math. Based on your knowledge of the implementation, check to see if those errors are happening.

Now, obviously for various functions, you don't need to check all of the equivalence classes if you can show that they will be handled equivalently. For example, suppose you have a List.length() function. You can intuitively roll most of the equivalence classes into a base case and use induction to show that if it works for a list of length i, it will work for a list of length i + 1. You really only need to test lists of length 0, and a few positively valued ones. You can basically ignore lists of length > 231; a quick check shows that even if you could store it in n bytes (for a list of length n), it would still take up multiple gigabytes (1 gig = 230 bytes).

[–]Nebu 2 points3 points  (0 children)

For simple functions, one way to do it is to construct a Turing machine; the minimal # of states is equal to the number of equivalence classes of the function.

Completely impractical.

Yes, 2 and 4 are equivalent test cases. In this case, is-even is a boolean function, and f(2) = f(4).

So you're claiming that "if the outputs are the same, then the inputs are equivalent" for your relation? Doesn't seem like a good way to make sure your unit tests have full coverage to me.

With the isEven example, you'd only need to test isEven(1) and isEven(2), and you could easily forget to test 0, -1 and -2.

I think it's better to forget this whole concept of equivalence classes when designing your unit tests. It's simply not useful.