I currently have the following method:
public void SetNewRandomValue() {
double newValue = numberGenerator.GenerateDouble(
genesValuesInterval.MinimumValue,
genesValuesInterval.MaximumValue
);
this.value = newValue;
}
What should be the guidelines for deciding how many tests (and which tests) to make to this method? I currently have done the following one (only after implementing the method -- that is, not test-first):
var interval = new Interval(-10, 10);
var numberGeneratorMock = new Mock<INumberGenerator>(MockBehavior.Strict);
var numberGenerator = numberGeneratorMock.Object;
double expectedValue = 5.0;
numberGeneratorMock.Setup(ng =>
ng.GenerateDouble(interval.MinimumValue, interval.MaximumValue))
.Returns(expectedValue);
var gene = new Gene(numberGenerator, 0, new Interval(-10, 10));
gene.SetNewRandomValue();
Assert.AreEqual<double>(expectedValue, gene.Value);
that basically just tests one situation. Regression-testingwise I'd say that I can't think of a way of messing up the c开发者_如何学Code, turning it into mal functioning code and still have the test pass, that is, I think the method looks decently covered.
What are your opinions on this? How would you handle this little method?
Thanks
I would examine the code coverage with whatever testing tool you use, if a code coverage is available for your testing framework.
I personally like to work with either Microsoft Testing Tool
or NUnit Testing Framework
. I can then right-click my tests project and Test with NCover
(while using NUnit), which will run the tests and tell me the percentage of code covered for each of my objects and tests.
I say that when you'll be done checking the code coverage which would result of at least a 98% code coverage, your code is likely to be well tested.
I'd recommend taking a look at Pex - it can really help generate the kind of unit tests you're looking for (i.e. figure out the different potential paths and results given a method and return value).
That test looks fine. The only thing you can actually assert about SetNewRandomValue
is that the Value
member is assigned afterward. You've mocked out the call to GenerateDouble
and verified that Value
contains the expected number, so you should be good.
You could also write a test to document (and verify) the expected behavior of Gene.SetNewRandomValue
when NumberGenerator.GenerateDouble
returns a value outside the specified interval.
You could definitely make a case for not unit testing this. IMHO, code inspection is a perfectly valid test methodology. You generally don't test things like property setters/getters, I think this method is simple enough to avoid unit testing for the same reason.
That said, if you really do want to test it, here's what I'd do: I'd test it with a couple values, not just once with 5. (SetNewRandomValue could be implemented as this.value = 5;
, which should not pass.) I'd test it with a non-integer number, to confirm there's not a oddball cast to integer in there.
You could test that it's calling GenerateDouble with the proper parameters, though that's really testing an implementation detail. (SetNewRandomValue could be implemented as numberGenerator.GenerateDouble(0, interval.max - interval.min) + interval.min;
, and that shouldn't fail the test.) You could use a real random number generator, and do SetNewRandomValue a few thousand times, and test that the values are evenly distributed in your expected range.
The method is doing three things:
Calling numberGenerator.GenerateDouble
with genesValuesInterval.MinimumValue
as the first parameter,
and with genesValuesInterval.MaximumValue
as the second parameter,
and setting this.value
to the result of that call.
Your test tests the third of these things, but not the first two. You could write two more tests that check the mock is called with the correct first and second parameters.
Edit (responding to comments below):
If the intended behaviour of this method is to set this.value
to a random double within a previously specified range, then the above three tests are useful (assuming genesValuesInterval
min and max are the previously specified range and that you have tests in place to assert that numberGenerator.GenerateDouble(min, max) returns a double within the specified range.
If the intended behaviour of this method is just to set this.value
to a random double within (Double.MinValue, Double.MaxValue), then the first two tests are unnecessary as this is just an implementation detail.
If the inted
To answer how to test it, you should be able to describe what is the desired behavior.
Looking at your code, I assume that "Gene.SetNewRandomValue" is supposed to set self.Value
to a number which falls within the Interval passed to the constructor.
I'm not super familiar with the Mock
class, so I may be off base, but it appears that you are not testing that. What if your implementation had this typo?
double newValue = numberGenerator.GenerateDouble(
genesValuesInterval.MinimumValue,
genesValuesInterval.MinimumValue
);
Wouldn't your test still pass?
精彩评论