1

I have a short function which gets an array and shuffles the values "around".

array_name.sort(function() { return 0.5 - Math.random() });

How can I test that I get a different array then I had before?

Of course I can mock the array, and then test if

array_name[2] != array_after[2];

But, as its random, it could happen that sometimes this position is equal and sometimes not.

What is a good approach to this?


So, its about testing the randomness

I have an approach, and of course my problem:

it('different option order when randomization is true', function() {
  var array = // getting from json.file here
  var array_after = question.shuffle(array);

  expect(array[4].text.localeCompare(array_after[1].text)).toBe(0);

});

Of course, i cannot say now that this is always different. Because i run my tests several times, and sometimes they are the same, and sometimes not...

ohboy21
  • 4,259
  • 8
  • 38
  • 66
  • Compare all occurrences in the array for equality. This "random" sorting algorithm of yours isn't a true random sort, though. If you have an array like this: `[0,1,2,3,4,5,6,7,8,9]`, `9` is _very_ unlikely to be moved to index `0` – Cerbrus Apr 30 '14 at 08:25
  • possible duplicate of [How to randomize (shuffle) a javascript array?](http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array) Clarification: You seem to be looking for a proper algorithm to randomize the array. – Cerbrus Apr 30 '14 at 08:31
  • I just have an array of objects, like 4 to 10. An object contains of a text and a value. So i just want to shuffle these few things. A complex shuffle algorithm seems overweighted for me... – ohboy21 Apr 30 '14 at 08:37
  • [comparing-two-arrays-in-javascript](http://stackoverflow.com/questions/7837456/comparing-two-arrays-in-javascript) – Bakudan Apr 30 '14 at 08:41
  • It may be a bit overkill, but your current algorithm isn't a true random sort. Any way, if I understand the question correctly, you're __not__ looking for a different RNG, just for a way to check __if__ the arrays are randomized? – Cerbrus Apr 30 '14 at 08:41
  • Yeah, right! I just want to test that they are different. True randomization is not possible, so i think in this case, i shouldn't care how close i get to "true random" – ohboy21 Apr 30 '14 at 08:43
  • In that case, my answer might be the solution. – Cerbrus Apr 30 '14 at 08:45
  • @askrufus: Are you only looking for a way to compare two arrays of do you want the shuffle function to always return a different array in your test? – flitig Apr 30 '14 at 09:09
  • Thank you very much! Is there a way to avoid those few % where the test fails? – ohboy21 Apr 30 '14 at 09:20
  • 1
    Ehm, re-shuffle before the `expect`, if they're equal. The chances of the array still being the same are very slim then, but theoretically still possible. – Cerbrus Apr 30 '14 at 09:23

2 Answers2

3

What you're after is a seeded random number generator. In your tests you can control the seed and verify that different seeds consistently generates different numbers.

See http://indiegamr.com/generate-repeatable-random-numbers-in-js/ for more information.

Related questions:

Community
  • 1
  • 1
flitig
  • 531
  • 2
  • 11
  • This would allow him to ensure the "randomisation" happens the same each time, and therefore he can guarantee that the array will be different after it is sorted. – Dean Barnes Apr 30 '14 at 08:34
  • 1
    As I understood it, he needs to make sure his tests don't fail in the event the random shuffling happens to generate the same array. Your unit tests should be repeatable. – flitig Apr 30 '14 at 08:34
-1

If you need to compare if the before / after arrays are indeed different, do something like this:

function arraysAreEqual(before, after){
    if(before.length !== after.length){
        return false;
    }
    for(var i = 0; i < before.length; i++){
        if(before[i] !== after[i]){
            return false;
        }
    }
    return true;
}

Depending on the contents of the arrays, you may need to modify the equality check in the for loop to account for nested arrays / objects.

Assuming:

var myArray = [
    {text: 'foo', value: 1},
    {text: 'bar', value: 2}
]

You can use this, for example:

if(before[i].text !== after[i].text ||
   before[i].value !== after[i].value){
    return false;
}

With this function, you should be able to use:

expect(arraysAreEqual(array, array_after)).toBe(false);

However, the test case will fail in the (improbable, but possible) case the randomizer returns the same array as the input.

Cerbrus
  • 70,800
  • 18
  • 132
  • 147
  • This effectively compares the arrays, but it doesn't solve the case when the shuffle function generates the same array order. – flitig Apr 30 '14 at 08:53
  • @flitig: Is that a case that should pass, then? It's unlikely that the in / out arrays are the same. I don't see how one can test if the randomizer "works" in cases where it returns a unchanged array. Maybe a small failure rate (As in _"in 2% of the test cases, the output can be the same as the input"_), should be tolerated. – Cerbrus Apr 30 '14 at 08:57
  • 2
    Sure, I see your point. I could accept that in production there's the off chance that the randomizer outputs the same array. However, I would not accept that my test suite will fail in 2% of the test runs. That's a fragile test and I would sooner remove it completely. A seeded randomizer will repeatedly work and test the functionality, why not use that? – flitig Apr 30 '14 at 09:04
  • @flitig: Hm, I see now, a seeded randomizer should consistently provide the same results for the same input (array / seed value combination) But is it productive to change the randomization just for the sake of passing test? I guess that's up to the OP. – Cerbrus Apr 30 '14 at 09:08
  • 1
    I think that comparing two arrays is pretty much a trivial task. I would personally rely on a library to do it in a cross-browser way.The non-trivial task is to test if the "random sort" or shuffling algorithm produces sequences drawn from a target probability distribution (uniform, normal). That could take a few iterations of reshuffling. – Leonidas Kapsokalivas Apr 18 '15 at 22:06
  • Did you really have to downvote this answer, just because I'm not using some kind of library to check for equality? – Cerbrus Apr 19 '15 at 07:09