0

Recently getting into adding unit tests to all my old projects to improve maintainability when I came across an interesting scenario regarding the suitability of adding assume() statements under cases where failure of the assumed case is a remote possibility.

One such case is with the class UUID and it's randomUUID() method. Given a scenario where a particular test depends on two randomly generated UUID to be distinct, is it excessive/unnecessary to add an assumption check for this case, e.g:

UUID firstUID = UUID.randomUUID();
UUID secondUID = UUID.randomUUID();

// Is this test excessive
assumeFalse(firstUID.equals(secondUID));

// Rest of test here

Whilst it can be seen from many places including here that UUID collisions are practically impossible, the javadoc for such a method does not claim it to be:

Static factory to retrieve a type 4 (pseudo randomly generated) UUID. The UUID is generated using a cryptographically strong pseudo random number generator.

The clause cryptographically strong pseudo random number generator is assuring but no explicit statement is given to the uniqueness of generated UUIDs. This means that potentially future implementations of the randomUUID() could change it's implementation such that collisions become more likely without breaking the declared contract of the method.

Whilst this case appears to be quite isolated, it does pop up from time to time especially when dealing with random number generation (also with prime number generation). From my perspective, adding a assumption clause does not contribute much to a performance hit so I left it in. But overall, are high probability (essentially practically impossible to fail) assumptions a good idea to add during unit tests? Or are they excessive? To take this further, are there guidelines to how likely a given assumption must fail before an actual assumption clause be written for them? I'm guessing assumeFalse(the world is ending) would be considered excessive.

P.S: the actual code under specification uses a third party UUID generation system that is unknown to me but guarantees uniqueness. As this case is an extension to the original API I'm substituting their UUID generation with a dummy randomUUID() such that the assumption is only probable for the test (100% for the actual code).

The alternative would be to write systems that guarantees the conditions (rather than just have a assumed high probability for them) though I find this excessive for small tests.

Community
  • 1
  • 1
initramfs
  • 8,275
  • 2
  • 36
  • 58

2 Answers2

2

Well, the whole thing is probably pretty much opinion-based, but the main problem I see here is not the performance hit, it's that you are testing something random that (in the worst case) will sometimes happen and sometimes not. What do you do then? Re-running the test will provide a different result. So what does this help you? You will realize for sure that it can happen, ok, but knowing this should not be the result of experimentation (for which unit tests are the wrong tool) but of reading documentation and code.

So I think you are working on the wrong level here: You should finde out (ONCE) if this is possible, decide if this case is acceptable, how to deal with this case and then test YOUR code dealing with this issue. (And if you need to test the framework you are using, you are using the wrong one in any way.)

Florian Schaetz
  • 10,454
  • 5
  • 32
  • 58
0

Instead of using an assumeFalse I would put generation of secondUID in a while loop. Regenerate secondUID until it no longer equals firstUID. This way you don't get a test failure on the extremely remote chance when firstUID equals secondUID.

sircody
  • 214
  • 1
  • 5