So I have this reaaaally long method that I want to test. I could probably break it some other 4-5 methods, but I don’t want to make those methods public (and although I could, I’d like to stay away, if possible, from turning them into package-protected/internal):
If my math isn’t wrong, to test this as it is I’ll need something like 8 tests. Dividing this in smaller methods wouldn’t make me have to make less unit-tests, would it?
The big problem I see with creating smaller methods(for testing) besides the visility issue is the need to pass to those small methods lots of arguments.
Although it was me who originally wrote this code, I still find it hard to understand.
So my question is…how to test this?!? How would you do it? Should I restructure this in any way?
public Genoma GenerateOffspring(Genoma genoma1, Genoma genoma2) {
if (genoma1.NumberOfGenes != genoma2.NumberOfGenes) throw new ArgumentException("Both individuals must have the same size!");
if (genoma1.NumberOfGenes == 0 || genoma2.NumberOfGenes == 0) throw new ArgumentException("0-sized genomas not allowed!");
if (genoma1.NumberOfGenes == 1) {
if (numberGenerator.GenerateInteger(0, 2) == 0) {
return genoma1;
} else {
return genoma2;
}
}
int cutPoint = numberGenerator.GenerateInteger(1, genoma1.NumberOfGenes);
Genoma parent1;
Genoma parent2;
if (numberGenerator.GenerateBool()) {
parent1 = genoma1;
parent2 = genoma2;
} else {
parent1 = genoma2;
parent2 = genoma1;
}
Genoma offspring = parent1.Clone();
if (numberGenerator.GenerateBool()) {
for (int i = 0; i < cutPoint; ++i) {
offspring.SetGeneAt(i, parent2.GetGeneAt(i));
}
} else {
for (int i = cutPoint; i < offspring.NumberOfGenes; ++i) {
offspring.SetGeneAt(i, parent2.GetGeneAt(i));
}
}
return offspring;
}
Thanks
The main thing to keep in mind is, when you start testing, you will run all tests, but for a given test, if it fails one assertion at some point, it will stop, meaning that what is after it will not be tested because it is assumed to require what was already not correctly asserted.
The good thing about dividing it into smaller methods would be that you would end up getting more things that could be tested independently, but the increase in arguments that you mention suggests that it would not be a “natural” thing to do, so you should keep it all in same test because you are, according to your words, seeing the whole function as a unit itself, and so, one unit test should test that unit.
Additionally, the increase in arguments would also make your code less pretty, and less efficient, I think.
I hope that helps.