Before this question is marked as duplicate, please read it. ;)
There are already several questions about coverage tools and such, however this is a bit different than the usual ones (I hope).
According to wikipedia there are several different kind of 'coverage' variations that affect several different aspects of the term 'coverage'.
Here a little example:
public class Dummy {
public int a = 0;
public int b = 0;
public int c = 0;
public void doSomething() {
a += 5;
b += 5;
c = b + 5;
}
}
public class DummyTest {
#Test
public void testDoSomething() {
Dummy dummy = new Dummy();
dummy.doSomething();
assertEquals( 10, dummy.c );
}
}
As you can see, the test will have a coverage of 100% lines, the assertion on the value of field 'c' will cover this field and indirectly also cover field 'b', however there is no assertion coverage on field 'a'.
This means that the test covers 100% of the code lines and assures that c contains the expected value and most probably also b contains the correct one, however a is not asserted at all and may a completely wrong value.
So... now the question: Is there a tool able to analyze the (java) code and create a report about which fields/variables/whatever have not been (directly and/or indirectly) covered by an assertion?
(ok when using getters instead of public fields you would see that getA() is not called, but well this is not the answer I'd like to hear ;) )
As you can see, the test will have a coverage of 100% lines, the assertion on the value of field 'c' will cover this field and indirectly also cover field 'b', however there is no assertion coverage on field 'a'. This means that the test covers 100% of the code lines and assures that c contains the expected value and most probably also b contains the correct one, however a is not asserted at all and may a completely wrong value.
Well, "cover" unfortunately means different things to different people... This test indeed exercises 100% of the code lines, but it does not test them all.
What you're looking for is handled well by mutation testing.
Have a look at Jester, which uses mutation testing to report on code coverage.
There are hundreds of definition of "test coverage", of which the COTS tools only handle a very few at best. (My company builds test coverage tools so we track this kind of thing). See this lecture on test coverage for an interesting overview.
The closest definition I have heard is one for data coverage; depending on your definition :-{ it tells you that each data item has been written and read during execution. The lecture talks about verifying that every write and every read has been exercised as a special case.
I don't know the hundreds of definitions by heart, but you may have invented yet one more: data coverage restricted to assertions.
there are Assertions in Java if that is what you are looking for.
To see how much code has been covered there are tools that you can use here are some examples:
cobertura
clover
Related
From the design perspective, I am wondering should I test the data, especially if it's a generally known data (not something very configurable) - this can apply to things like popular file extensions, special IP addresses etc.
Suppose we have a emergency phone number classifier:
public class ContactClassifier {
public final static String EMERGENCY_PHONE_NUMBER = "911";
public boolean isEmergencyNumber(String number) {
return number.equals(EMERGENCY_PHONE_NUMBER);
}
}
Should I test it this way ("911" duplication):
#Test
public testClassifier() {
assertTrue(contactClassifier.isEmergencyNumber("911"));
assertFalse(contactClassifier.isEmergencyNumber("111-other-222"));
}
or (test if properly recognized "configured" number):
#Test
public testClassifier() {
assertTrue(contactClassifier.isEmergencyNumber(ContactClassifier.EMERGENCY_PHONE_NUMBER));
assertFalse(contactClassifier.isEmergencyNumber("111-other-222"));
}
or inject "911" in the constructor,which looks the most reasonable for me, but even if I do so - should I wrote a test for the "application glue" if the component was instantiated with proper value? If someone can do a typo in data (code), then I see no reasons someone can do a typo in tests case (I bet such data would be copy-paste)
What is the point in test data that you can test? That constant value is in fact constant value? It's already defined in code. Java makes sure that the value is in fact the value so don't bother.
What you should do in unit test is test implementation, if it's correct or not. To test incorrect behaviour you use data defined inside test, marked as wrong, and send to method. To test that data is correct you input it during test, if it's border values that are not well known, or use application wide known values (constants inside interfaces) if they're defined somewhere already.
What is bothering you is that the data, that should be well known to everyone) is placed in test and that is not correct at all. What you can do is to move it to interface level. This way, by design, you have your application known data designed to be part of contract and it's correctness checked by java compiler.
Values that are well known should not be checked but should be handled by interfaces of some sort to maintain them. Changing it is easy, yes, and your test will not fail during that change, but to avoid accidents with it you should have merge request, reviews and tasks that are associated with them. If someone does change it by accident you can find that at the code review. If you commit everything to master you have bigger problems than constants doubly defined.
Now, onto parts that are bothering you in other approaches:
1) If someone can do a typo in data (code), then I see no reasons someone can do a typo in tests case (I bet such data would be copy-paste)
Actually, if someone changes values in data and then continues to develop, at some point he will run clean-install and see those failed tests. At that point he will probably change/ignore test to make it pass. If you have person that changes data so randomly you have bigger issues, and if not and the change is defined by task - you made someone do the change twice (at least?). No pros and many cons.
2) Worrying about someone making a mistake is generally bad practice. You can't catch it using code. Code reviews are designed for that. You can worry though about someone not correctly using the interface you defined.
3) Should I test it this way:
#Test
public testClassifier() {
assertTrue(contactClassifier.isEmergencyNumber(ContactClassifier.EMERGENCY_PHONE_NUMBER));
assertFalse(contactClassifier.isEmergencyNumber("111-other-222"));
}
Also not this way. This is not test but test batch, i.e. multiple tests in the same method. It should be this way (convention-s):
#Test
public testClassifier_emergencyNumberSupplied_correctnessConfirmed() {
assertTrue(contactClassifier.isEmergencyNumber(ContactClassifier.EMERGENCY_PHONE_NUMBER));
}
#Test
public testClassifier_incorrectValueSupplied_correctnessNotConfirmed() {
assertFalse(contactClassifier.isEmergencyNumber("111-other-222"));
}
4) it's not necessary when method is properly named, but if it's long enough you might consider naming the values inside test. For example
#Test
public testClassifier_incorrectValueSupplied_correctnessNotConfirmed() {
String nonEmergencyNumber = "111-other-222";
assertFalse(contactClassifier.isEmergencyNumber(nonEmergencyNumber));
}
External constants as such have a problem. The import disappears and the constant is added to the class' constant pool. Hence when in the future the constant is changed in the original class, the compiler does not see a dependency between the .class files, and leaves the old constant value in the test class.
So you would need a clean build.
Furthermore tests should be short, clear to read and fast to write. Tests deal with concrete cases of data. Abstractions are counter-productive, and may even lead to errors in the test themselves. Constants (like a speed limit) should be etched in stone, should be literals. Value properties like the maximum velocity of a car brand can stem from some kind of table lookup.
Of course repeated values could be placed in local constants. Prevents typos, easy - as local - abstraction, clarifies the semantic meaning of a value.
However as cases in general will use constants maybe twice or three times (positive and negative test), I would go for bare constants.
In my opinion the test should check behaviour and not the internal implementation.
The fact that isEmergencyNumber verifies the number over constant declared in the class you're trying to test is verification over internal implementation. You shouldn't rely on it in the test because it is not safe.
Let me give you some examples:
Example #1: Someone changed EMERGENCY_PHONE_NUMBER by mistake and didn't notice. The second test will never catch it.
Example #2: Suppose ContactClassifier is changed by not very smart developer to the following code. Of course it is completely edge case and most likely it will never happen in practice, but it also helps to understand what I mean.
public final static String EMERGENCY_PHONE_NUMBER = new String("911");
public boolean isEmergencyNumber(String number) {
return number == EMERGENCY_PHONE_NUMBER;
}
In this case your second test will not fail because it relies on internal implementation, but your first test which checks real word behaviour will catch the problem.
Writing a unit test serves an important purpose: you specify rules to be followed by the method being tested.
So, when the method breaks that rule i.e. the behavior changes, the test would fail.
I suggest, write in human language, what you want the rule to be, and then accordingly write it in computer language.
Let me elaborate.
Option 1 When I ask ContactClassifier.isEmergencyNumber method, "Is the string "911" an emergency number?", it should say yes.
Translates to
assertTrue(contactClassifier.isEmergencyNumber("911"));
What this means is you want to control and test what number is specified by the constant ContactClassifier.EMERGENCY_PHONE_NUMBER. Its value should be 911 and that the method isEmergencyNumber(String number) does its logic against this "911" string.
Option 2 When I ask ContactClassifier.isEmergencyNumber method, "Is the string specified in ContactClassifier.EMERGENCY_PHONE_NUMBER an emergency number ?", it should say yes.
It translates to
assertTrue(contactClassifier.isEmergencyNumber("911"));
What this means is you don't care what string is specified by the constant ContactClassifier.EMERGENCY_PHONE_NUMBER. Just that the method isEmergencyNumber(String number) does its logic against that string.
So, the answer would depend on which one of above behaviors you want to ensure.
I'd opt for
#Test
public testClassifier() {
assertTrue(contactClassifier.isEmergencyNumber("911"));
assertFalse(contactClassifier.isEmergencyNumber("111-other-222"));
}
as this doesn't test against something from the class under test that might be faulty. Testing with
#Test
public testClassifier() {
assertTrue(contactClassifier.isEmergencyNumber(ContactClassifier.EMERGENCY_PHONE_NUMBER));
assertFalse(contactClassifier.isEmergencyNumber("111-other-222"));
}
will never catch if someone introduces a typo into ContactClassifier.EMERGENCY_PHONE_NUMBER.
In my opinion that is not necessary to test this logic. The reason is: this logic is trivial for me.
We can test all line of our code, but I don't think that is a good idea to do this. For example getter and setter. If we follow the theory to test all line of code, we have to write test for each of getter and setter. But these tests have low value and cost more time to write, to maintain. That is not a good investment
We have been assigned an open source software to test!
The software has 3 packages and each package has 10 or more classes and each class might have dozens of methods.
My question is that before I start structural (white-box) testing, do i need to understand every line of code in the software?
Do I need to understand the whole flow of program starting from main() method?
What is the approach I should take?
If you have specs on what each method is supposed to do: What is expected output for specified input then no you don't need to go into implementation details of those methods. Normally this should be written down!
You could write unit tests that check if methods are satisfying predefined contracts (if they exist).
If you don't have specs or with recent trend 'UserStories' you need to 'reverse engineer your specs' :) You would need to analyse each method to understand what is it doing, next you will check where those methods are being called in order to figure out what are the possible values passed in the method calls. Also from the calling methods you might get the idea what are the corner cases. And those you definitely want to test.
.... and slowly you learned the whole code :)
No, you don't have to understand every line of code to write Unit tests. I'm not so experienced with unit tests yet, but what if seen so far is testing every (or most) methods that respond differently to a certain input (--> arguments, object variables ...).
So you have to know what a method does, when it successfully does things, and when it is suppose to fail. And for some methods even the turning points between those cases are important.
For Example
Let's say we have a method that sums two ints, that have to be equal to or larger than 0:
public static int sumInts(int a, int b) {
if (a < 0 || b < 0) throw new IllegalArgumentException("'a' and 'b' should be 0 or above!");
return a + b;
}
What you could test:
if a = 49 and b = 16, does it return 65?
if a = -3 and b = 4, does it throw an exception?
if a = 5 and b = -13, does it throw an exception?
if a = -46 and b = -13, does it throw an exception?
if a = 0 and b = 0, does it return 0?
if a = -1 and b = -1, does it throw an exception?
Of course, this is just a very simple example. What you test depends on your method. For this method, the last two tests would likely be totally unneeded. But there are methods that are more complex, where those could be useful.
There are several types of tests.
Unit test tests the functionality of each method on different cases of input data. Like, if you have a BigInteger fact(int n) method, you have to write tests on normal positive integers, zero, negative integers and max/min values. There are several libraries which'll help you: JUnit,TestNG, etc.
Integration test tests the whole your application, all packages and classes as a group. See Arquillian project.
Also, you can write black-box tests using Selenium.
Much more types of testing like regression testing, load testing, etc. This is the work for QA engineer.
After dark ages of software industry the community finally came to some good unit testing practices:
Code coverage. We would be living in caves without code coverage metrics.
Fault injection helps you in building more robust and stable software.
Wide mocking usage to write more specific tests without dirty influence of the rest of your application.
Currently, I'm in a position where I'm to write unit tests for source code I have complete visibility of (which I think means it's considered white box testing?). So, this isn't test-driven development.
Reading this (What is the difference between integration and unit tests?) clarified a lot about what the purpose of all this is, but I'm confused about my current position still.
Let's say I have a method like so:
/* Some basic description on what doSomething() does */
public int doSomething(Var someVariable) {
int someInteger = [code does a bunch of stuff to get this];
someInteger = someOtherClassObject.doSomethingElse(someInteger);
return someInteger;
}
Now, I don't really know what doSomething() is supposed to do. The documentation isn't enough to really tell me what int is supposed to come out based on someVariable, and I'm not familiar enough with the source code to really come up with it myself.
But I do have the implementation, so I look at the method, put in some Var as the input, and follow the code and assert against what it looks like it would return.
public void testDoSomething() {
ClassWithDoSomething object = new ClassWithDoSomething();
assertEquals([what it looks like it would return], object.doSomething(new Var([some input would go here]));
}
Where some way, somehow, I mock out the doSomethingElse() call and the Var constructor (and other external class dependencies if need be).
I don't know whether this is the right way to go about these unit tests. I think I'm isolating the method as I should, but I don't know how meaningful my assert is in determining whether there is a bug or not, because I know just what the method doSomething() is supposed to do in code, and how it's going to go about it, and so I've written my assertion to get that result.
The answer I've read details how unit tests are beneficial due to the method doSomething()'s isolated failure. But when would its unit test ever fail, other than when doSomething()'s implementation changes (which would mean a change in the unit test)?
Is this an issue of not knowing the source code well enough/the source code not being well documented enough to just be able to know what output I should be getting?
If [code does a bunch of stuff to get this] was really just someVariable + 3 where someVariable was an int, is it considered a meaningful assert to assert that the return value is someVariable + 3 when I know the test is going to pass based on that implementation?
But when would its unit test ever fail?
You have it exactly right; the unit test will fail when doSomething's implementation changes. The point of the unit test is to catch it when a seemingly-innocuous change actually breaks the method.
Unit tests often look similar to the code snippet you posted:
public void testDoSomething() {
ClassWithDoSomething object = new ClassWithDoSomething();
object.someOtherClassObject = new MockOtherClass();
assertEquals(4, object.doSomething(new Var("Input that maps to 4"));
}
Both SomeOtherClass and MockOtherClass implement an IOtherClass interface that specifies doSomethingElse. MockOtherClass simply returns the input when you call its doSomethingElse method.
i'd say it's pointless to write unit testing if you don't know what the code is expected to do.
unit testing is checking if given some input code behaves correctly. if you don't know what does 'correctly' mean then how can you test it? you have to understand intention of the code before writing valuable tests.
the situation is a bit different if you write tests in order to rewrite the source code from scratch. in this case tests are the best safety net you can get because they document the actual behaviour and guarantee it won't change. but even in this case, without knowing what the code does, it's easy to miss some corner cases.
so i recommend to always know the intention of the code before you write tests.
This example is custom made to ask my doubt.
Object Car {
color:null
tyre : 0;
}
fillCar(Object Car, boolean b) {
if (b) {
Car.color = "Red"
} else {
Car.tyre = 4;
}
}
Now i need to unit test my code.
My test1 is (Car, true) and test2 is (Car, false).
My question:
Do i need to test "tyres == 4" when in test1 and on similar lines do i need to check "color == null" when test2 ?
The answer is YES if this is part of the functional requirement of the method.
For example, if your specifications say that when True the value of tyre must be 4 and other variables will not matter, then it is not necessary. But if your specifications say that not only tyre must be 4 but the rest of variables must remain with the same value, then you should check that out too.
Take into account that Unit test not only are useful for checking that your code is fine, but also for making sure that when your code in the future, you do not corrupt the expected functionality.
Generally, there is no harm in testing all parts of the code. In fact, I would encourage it. It's a very easy way of checking that no mistakes have been made in the logic.
In this case, the code is simple enough to see the result. However, it could become much more complex if Car is extended, or more functionality added.
There is a lot of argument about this but unit testing started to make sense to me once I focused on verifying the interface. In this case you have a function which exposes an interface where you can pass in a car-object and a boolean and then have certain modifications made to the car object depending on the value of the boolean. You quite rightly see two unit tests covering that and personally I would stop there. If you are worried about nulls showing up you can cover that in the unit tests when the car objects are constructed. If you assign something other than a straight forward literal that might be a null then tests for nulls would make sense.
One more tip - unit testing works much better for me within the context of test driven design (TDD). YMMV but I find non-TDD code very hard to unit test.
Finally - just a mention that I found learning TDD/unit-testing is well worth it.
I could not confirm whether to do these tests. It seems the set and get method is so simple,such as:
setA(String A) {
this.A = A;
}
getA(){
return A;
}
Any ideas would be appreciated!
Thanks,
Joseph
I've only seen a very few problems with getters and setters in the wild, and only one of those could have been detected via a unit test, and only then if all of the getters and setters were tested together, rather than by individual test methods.
Consider the copy/paste mistake of reusing the same field from two different pairs of getters/setters. I.e.,
public void setA(Object a) {
this.a = a;
}
public Object getA() {
return a;
}
public void setB(Object a) {
this.a = a;
}
public Object getB() {
return a;
}
Unit tests that focus on one setter/getter pair at a time won't expose the problem.
Modern IDEs will generate getters and setters on request, so this mistake is unlikely, but not everyone uses modern IDEs. (A vi user created the bug above.) And if these methods reside in a simple data-holder object, the problem may only show up a bit far from the cause.
For this reason, if I test getters and setters at all (and I often don't), it's from a single test method that calls all of the setters first with distinct values, then asserts on all of the getters.
One problem you've got to live with, though, is that there's no guarantee that a method that starts life as a "simple" getter or setter will stay that way when someone else gets their hands on the code and decides, say, that a getter is a good place do something that involves a side-effect.
General rule: Not much point in writing tests for getters and setters. Only if they have some additional logic, ie. are not pure accessors, you should write the tests.
The only time I would write tests specifically for set() and get() methods, is if there is some sort of logic inside them. Eg. limit an integer to between 1 and 8
public void SetA(int a)
{
if(a > 8 || a < 1)
{
throw new IndexOutOfBoundsException();
}
this.a = a;
}
Even though the code above is a very simple example, when you do this type of logic, it can be a good idea to run a test on them. Mainly for when your business rules change and you have to limit it to between 9 and 1 :)
A smart man once said "Test until fear turns to boredom". If you no longer fear that your super-simple code will break, don't write tests unless you're not bored writing those tests. And don't write tests just to "improve your metrics," that's just gaming the system. Write tests to make sure your code works, to improve robustness, and to create confidence that you can refactor freely.
Make a cost/benefit analisis
What would it gain
knowing that the private variable indeed get read/written
What would it cost
the time taken to write the testcase
the time spend, each time executing your testsuite
If you know there are no observable side-effects calling the getter or setter, I wouldn't bother.
Yes, in your case they are trivial - but on the other hand - two simple tests that fully count for quality metrics ;-)
I would create tests. Your application actually relies on the behaviour that the methods really store/access the field values and do not change anything.
Maybe, one day someone decides to change a field type or to add some unit conversion code to a setter/getter - a test will show, if the code still works or it will show, that more work is needed.
They are all same, I say like blank interfaces or business classes. Preprocessing should enable all needed or they are other kinds (doers that both shall return like respond and take 2 variables) language agnostically (even POSIX exit that now is void should use arguments since knowing way is very important)
Writing test cases for methods which can't fail seems disproportionate to me.
Only if the value of A is initialized by configuration or something which could fail
it is worth testing.
EDIT:
Another example when testing makes sense could be a flag 'overdrawn' if an accounts balance becomes negative and you want to check whether the flag was set correctly after calling a method withdraw().
Unit tests are supposed to be the documentation for how the system is supposed to work. Although people often skip unit tests for Properties because the functionality is trivial,
if the tests are the documentation and especially if someone else is going to do the implementation then tests for Properties should be written.
That said, when I am both writing the tests and doing the implementation, I usually skip writing tests for Properties unless they do something more than a simple get/set or if I have spare time, which is a rare thing.