Testing a method producing a random result

2019-07-19 23:26发布

I want to test this method:ArrayList<File> songs;

public void playRandomSong()
{
    Random random = new Random();
    int iNextSong = random.nextInt(songs.size());
    File songToPlay = songs.get(iNextSong);
    if (mediaPlayer != null && mediaPlayer.isPlaying())
        mediaPlayer.stop();
    mediaPlayer = new MediaPlayerImpl(songToPlay, new WhenDone());
    mediaPlayer.play();
    currentSong = songToPlay;
}

I'm thinking in this way: Run the method multiple times and see if it returns one of the elements more than once. But how would I write that in code?

4条回答
劳资没心,怎么记你
2楼-- · 2019-07-19 23:40

I see another problem in your code: if you want to play songs in random order you are doing that in wrong way. This algorithm should not repeat song until all songs in list are played. To achieve that there is an algorithm called Knuth shuffling. You can take it from Collections class: java.util.Collections#shuffle.

查看更多
我命由我不由天
3楼-- · 2019-07-19 23:44

Random does not guarantee that it will not return the same value twice... So you can not test "see if it returns one of the elements more than once"

If you need that you will have to implement a Set around the Random, but be aware of the Birthday paradox...

I think you have 2 options:

1 : You may try to seed your Random, so you can predict the sequence...

2 : Remove the Random and make use of the [Collections.shuffle][1] to shuffle you arrayList

With Option 1 you will have to change the signature of your method.

With Option 2 you will also play every song once.

查看更多
萌系小妹纸
4楼-- · 2019-07-19 23:50

Here is an article on randomness testing that you might find useful:

http://beust.com/weblog/2012/02/20/various-ways-to-get-randomness-wrong/

查看更多
做自己的国王
5楼-- · 2019-07-19 23:59

Instead of creating a RNG in your method

public void playRandomSong() {
  Random random = new Random();
  ...
}

you should pass the source of randomness in (this is called dependency injection)

public void playRandomSong(Random random) {
  ...
}

and then you can generate a Random instance with a known seed in your unit test to get repeatable but typical results.

public void testPlayRandomSong() {
  Random random = new Random(0xd5021e90339050ab);

  // Test that 1000 runs plays each song roughly the right number of times.
  ...
}
查看更多
登录 后发表回答