def test_sequence_less_than_dice_sides(self, capsys, monkeypatch): # Test to see whether we can use a n-sided die to choose from # a sequence with less than n items src = RealDiceRandomSource(None) src.dice_sides = 6 # A length of 1 requires no rolls self.fake_input_values(["1"], monkeypatch) picked = src.choice([1]) out, err = capsys.readouterr() assert "roll" not in out assert picked == 1 # A length of 2,3 only requires 1 roll for choice_length in (2, 3): self.fake_input_values(["1"], monkeypatch) picked = src.choice(range(1, choice_length + 1)) out, err = capsys.readouterr() assert "roll 1 dice" in out assert picked == 1 # A length of 4,5 requires 2 rolls for choice_length in (4, 5): self.fake_input_values(["1", "1"], monkeypatch) picked = src.choice(range(1, choice_length + 1)) out, err = capsys.readouterr() assert "roll 2 dice" in out assert picked == 1
def test_no_hint_if_entropy_is_not_decreased(self, fake_input, capsys): # we do not issue the entropy warning if not neccessary fake_input(["1"] * 6) src = RealDiceRandomSource(None) picked1 = src.choice([1, 2, 3, 4, 5, 6]) picked2 = src.choice(range(1, 6 ** 2 + 1)) picked3 = src.choice(range(1, 6 ** 3 + 1)) assert picked1 == 1 assert picked2 == 1 assert picked3 == 1 out, err = capsys.readouterr() assert "entropy is reduced" not in out assert err == ""
def test_no_hint_if_entropy_is_not_decreased(self, fake_input, capsys): # we do not issue the entropy warning if not neccessary fake_input(["1"] * 6) src = RealDiceRandomSource(None) picked1 = src.choice([1, 2, 3, 4, 5, 6]) picked2 = src.choice(range(1, 6**2 + 1)) picked3 = src.choice(range(1, 6**3 + 1)) assert picked1 == 1 assert picked2 == 1 assert picked3 == 1 out, err = capsys.readouterr() assert "entropy is reduced" not in out assert err == ""
def test_choice_prints_hint_on_repeated_rolls(self, capsys, fake_input): # on short sequences (shorter than number of dice sides) # we give users hints to repeat dice rolls src = RealDiceRandomSource(None) src.dice_sides = 4 fake_input(["2", "3"]) # no value out of bounds (> 3) picked = src.choice([1, 2, 3]) out, err = capsys.readouterr() assert picked == 2 assert out.count("Please roll dice again") == 0 fake_input(["4", "4", "1"]) picked = src.choice([1, 2, 3]) out, err = capsys.readouterr() assert picked == 1 assert out.count("Please roll dice again") == 2
def test_choice_num_of_dice_for_seq_len36(self, fake_input): # choice() requires two dice for a sequence len of 6**2 fake_input(["1", "2"]) src = RealDiceRandomSource(None) sequence = list(range(6**2)) expected_index = 6 * (1 - 1) + (2 - 1) # = 6 x roll_1 + roll_2 - 1 assert src.choice(sequence) == sequence[expected_index]
def test_choice_num_of_dice_for_seq_len36(self, fake_input): # choice() requires two dice for a sequence len of 6**2 fake_input(["1", "2"]) src = RealDiceRandomSource(None) sequence = list(range(6 ** 2)) expected_index = 6 * (1 - 1) + (2 - 1) # = 6 x roll_1 + roll_2 - 1 assert src.choice(sequence) == sequence[expected_index]
def test_choice_num_of_dice_for_seq_len216(self, fake_input): # choice() requires three dice for a sequence len of 6**3 fake_input(["1", "2", "3"]) src = RealDiceRandomSource(None) sequence = list(range(6 ** 3)) # 216 # = 6^2 * (roll_1 - 1) + 6^1 * (roll_2 - 1) + (roll_3 - 1) expected_index = 0 + 6 + 3 - 1 assert src.choice(sequence) == sequence[expected_index]
def test_choice_copes_with_multicharacter_separator(self, fake_input): # choice() requires three dice for a sequence len of 6**3 fake_input(["1,,2 3"]) src = RealDiceRandomSource(None) sequence = list(range(6 ** 3)) # 216 # = 6^2 * (roll_1 - 1) + 6^1 * (roll_2 - 1) + (roll_3 - 1) expected_index = 0 + 6 + 3 - 1 assert src.choice(sequence) == sequence[expected_index]
def test_choice_copes_with_sequence_len_1(self, capsys, fake_input): # choice copes with sequences of len 1 src = RealDiceRandomSource(None) fake_input(["1"]) picked = src.choice([1]) out, err = capsys.readouterr() assert "roll" not in out assert picked == 1
def test_choice_num_of_dice_for_seq_len216(self, fake_input): # choice() requires three dice for a sequence len of 6**3 fake_input(["1", "2", "3"]) src = RealDiceRandomSource(None) sequence = list(range(6**3)) # 216 # = 6^2 * (roll_1 - 1) + 6^1 * (roll_2 - 1) + (roll_3 - 1) expected_index = 0 + 6 + 3 - 1 assert src.choice(sequence) == sequence[expected_index]
def test_choice_copes_with_small_sequences(self, capsys, fake_input): # We handle sequences correctly, that have less elements than the used # dice sides. src = RealDiceRandomSource(None) src.dice_sides = 6 # A length of 2,3 only requires 1 roll for choice_length in (2, 3): fake_input(["1"]) picked = src.choice(range(1, choice_length + 1)) out, err = capsys.readouterr() assert "roll 1 dice" in out assert picked == 1 # A length of 4,5 requires 2 rolls for choice_length in (4, 5): fake_input(["1", "2"]) picked = src.choice(range(1, choice_length + 1)) out, err = capsys.readouterr() assert "roll 1 dice" in out assert picked == 1
def test_choice_respects_dice_sides(self, capsys, fake_input): # we use the number of dice sides given by options dict. fake_input(["1", "2"]) # A Namespace, not a dict, is passed to the constructor. options = argparse.Namespace(dice_sides=2) # a coin src = RealDiceRandomSource(options) picked = src.choice(['a', 'b', 'c', 'd']) out, err = capsys.readouterr() # must throw a coin 2 times to pick one out of 4 items assert "Please roll 2 dice" in out assert picked == 'b'
def test_choice_distributes_equally(self, fake_input): # we distribute nearly equally over sequences sized # dice_sides**n src = RealDiceRandomSource(None) src.dice_sides = 3 dist = [0, 0, 0] fake_input(["1", "2", "3"]) for x in range(3): picked = src.choice([1, 2, 3]) dist[picked - 1] += 1 assert dist == [1, 1, 1]
def test_choice_distributes_equally_on_long_seq(self, fake_input): # we distribute nearly equally over sequences longer than # dice_sides**n src = RealDiceRandomSource(None) src.dice_sides = 2 dist = [0, 0, 0] fake_input(["1", "1", "1", "2", "2", "1", "2", "2"]) for x in range(8): picked = src.choice([1, 2, 3]) dist[picked - 1] += 1 assert dist == [4, 4, 0]
def test_hint_if_entropy_is_decreased(self, fake_input, capsys): # if len of choice is not a multiple of 6, entropy is decreased # (not the whole sequence is taken into consideration). We get # a warning in that case. fake_input(["1"]) src = RealDiceRandomSource(None) picked = src.choice([1, 2, 3, 4, 5, 6, 7]) assert picked == 1 out, err = capsys.readouterr() assert "entropy is reduced" in out assert "Using only first 6 of 7 words" in out assert err == ""
def test_choice_distributes_equally_on_short_seq(self, fake_input): # we distribute equally over sequences shorter than # dice_sides**n src = RealDiceRandomSource(None) src.dice_sides = 4 dist = [0, 0, 0] # a list of pairs in a row: 4-4 - 4-3 - 4-2 - ... - 1-3 - 1-2 - 1-1 rolled_values = list(chain.from_iterable( product(["4", "3", "2", "1"], repeat=2))) # 4 is not a valid roll value, must do a new roll then num_valid = len(rolled_values) - rolled_values.count("4") fake_input(rolled_values) for x in range(num_valid): picked = src.choice([1, 2, 3]) dist[picked - 1] += 1 assert dist == [8, 8, 8]
def test_choice_distributes_equally_on_short_seq(self, fake_input): # we distribute equally over sequences shorter than # dice_sides**n src = RealDiceRandomSource(None) src.dice_sides = 4 dist = [0, 0, 0] # a list of pairs in a row: 4-4 - 4-3 - 4-2 - ... - 1-3 - 1-2 - 1-1 rolled_values = list( chain.from_iterable(product(["4", "3", "2", "1"], repeat=2))) # 4 is not a valid roll value, must do a new roll then num_valid = len(rolled_values) - rolled_values.count("4") fake_input(rolled_values) for x in range(num_valid): picked = src.choice([1, 2, 3]) dist[picked - 1] += 1 assert dist == [8, 8, 8]
def test_non_numbers_as_input_are_rejected(self, fake_input): # Users might input non-numbers. We ask again then. fake_input(["no-number", "", "1"]) src = RealDiceRandomSource(None) assert src.choice([1, 2, 3, 4, 5, 6]) == 1
def test_choice_input_lower_value_borders(self, monkeypatch): # choice() does not accept "0" but it accepts "1" self.fake_input_values(["0", "1"], monkeypatch) src = RealDiceRandomSource(None) sequence = (1, 2, 3, 4, 5, 6) assert src.choice(sequence) == 1
def test_choice_accepts_tuples_of_numbers(self, monkeypatch): # the choice() method accepts tuples of numbers self.fake_input_values(["1"], monkeypatch) src = RealDiceRandomSource(None) assert src.choice((11, 12, 13, 14, 15, 16), ) == 11
def test_choice_accepts_list_of_chars(self, monkeypatch): # the choice() method accepts lists of chars self.fake_input_values(["1"], monkeypatch) src = RealDiceRandomSource(None) assert src.choice(['a', 'b', 'c', 'd', 'e', 'f']) == 'a'
def test_choice_accepts_list_of_strings(self, monkeypatch): # the choice() method accepts lists of strings self.fake_input_values(["1"], monkeypatch) src = RealDiceRandomSource(None) assert src.choice( ['val1', 'val2', 'val3', 'val4', 'val5', 'val6']) == "val1"
def test_choice_accepts_tuples_of_numbers(self, fake_input): # the choice() method accepts tuples of numbers fake_input(["1"]) src = RealDiceRandomSource(None) assert src.choice((11, 12, 13, 14, 15, 16), ) == 11
def test_choice_input_upper_value_borders(self, fake_input): # choice() does not accept "7" but it accepts "6" fake_input(["7", "6"]) src = RealDiceRandomSource(None) sequence = (1, 2, 3, 4, 5, 6) assert src.choice(sequence) == 6
def test_choice_accepts_list_of_strings(self, monkeypatch): # the choice() method accepts lists of strings self.fake_input_values(["1"], monkeypatch) src = RealDiceRandomSource(None) assert src.choice(['val1', 'val2', 'val3', 'val4', 'val5', 'val6']) == "val1"
def test_choice_len_too_short(self, monkeypatch): # We raise an exception if choice gets less than 6 elements. self.fake_input_values(["1"], monkeypatch) src = RealDiceRandomSource(None) with pytest.raises(ValueError): assert src.choice([1, 2, 3, 4, 5]) # list len < 6
def test_choice_accepts_list_of_chars(self, fake_input): # the choice() method accepts lists of chars fake_input(["1"]) src = RealDiceRandomSource(None) assert src.choice(['a', 'b', 'c', 'd', 'e', 'f']) == 'a'
def test_choice_accepts_list_of_strings(self, fake_input): # the choice() method accepts lists of strings fake_input(["1"]) src = RealDiceRandomSource(None) assert src.choice(['val1', 'val2', 'val3', 'val4', 'val5', 'val6']) == "val1"
def test_choice_accepts_list_of_strings(self, fake_input): # the choice() method accepts lists of strings fake_input(["1"]) src = RealDiceRandomSource(None) assert src.choice( ['val1', 'val2', 'val3', 'val4', 'val5', 'val6']) == "val1"