Unit testing - how do I test a function that returns random output?

后端 未结 6 832
半阙折子戏
半阙折子戏 2020-12-07 01:01

I have a function which takes in two parameters, and returns one or the other 50% of the time.

The unit test for this should determine that both parameters could be

6条回答
  •  不知归路
    2020-12-07 01:31

    You test it through separation and/or injection:

    // ** WARNING: Untested code
    

    Original

    void funcToTest(String a, String b) {
      int i = new Random().nextInt(2);
      return ((i == 0) ? a : b);
    }
    

    Separating

    void funcToTest(String a, String b) {
      return funcToTest(a, b, (new Random().nextInt(2) == 0));
    }
    void funcToTest(String a, String b, boolean r) {
      return (r ? a : b);
    }
    

    Now test

    funcToTest(String a, String b, boolean r).
    

    You're trusting that, if you test the above, then

    funcToTest(String a, String b)
    

    will work just work.

    Injecting

    interface BoolRandomizer {
      bool getBool();
    }
    BoolRandomizer BOOL_RANDOMIZER = new BoolRandomizer() {
      public bool getBool() { return (new Random().nextInt(2) == 0); }
    }
    BoolRandomizer ALWAYS_FALSE_RANDOMIZER = new BoolRandomizer() {
      public bool getBool() { return false; }
    }
    BoolRandomizer ALWAYS_TRUE_RANDOMIZER = new BoolRandomizer() {
      public bool getBool() { return true; }
    }
    
    class ClassUnderTest {
        private final BoolRandomizer br;
        ClassUnderTest() { this(BOOL_RANDOMIZER); }
        ClassUnderTest(BoolRandomizer br) { this.br = br; }
        void funcToTest(String a, String b) {
          return (br.getBool() ? a : b);
        }
    }
    

    Now test

    new ClassUnderTest(ALWAYS_FALSE_RANDOMIZER).funcToTest()
    

    and

    new ClassUnderTest(ALWAYS_TRUE_RANDOMIZER).funcToTest()
    

    There are of course more complex/slicker ways to do this, but this is the basic idea. I used these techniques for a deck of cards program to test the shuffle function. Another case: a function that uses current time by calling system API gettime() could be hard to test unless you are willing to run the unit test at very specific times of day :-). Separation and injection ease testing.

提交回复
热议问题