test_roll.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #!/usr/bin/env python3
  2. """
  3. This file tests src.get_roll.
  4. Three main parts are tested:
  5. general form, injection, and failure detection.
  6. """
  7. import unittest
  8. from src.gen_roll import get_roll
  9. from src.config import DICE, HITS, FAILS
  10. class TestRoll(unittest.TestCase):
  11. """Unittest Testcase for src.get_roll"""
  12. # neutral are all dice results minux the results of HITS and FAILS
  13. NEUTRAL_RES = set(DICE) - set(HITS) - set(FAILS)
  14. NEUTRAL_RES = list(NEUTRAL_RES)
  15. NON_FAILS = NEUTRAL_RES + HITS
  16. # general form
  17. def test_normal_length(self):
  18. """Tests if the result length is equal to the amount passed."""
  19. len_roll_result = len(get_roll(3)["result"])
  20. self.assertEqual(len_roll_result, 3, "amount of dice throws should be equal to results")
  21. def test_available_keys(self):
  22. """Tests if different amount roll dicts have all the necessary key"""
  23. keys = ["result", "hits", "fails", "isFailure"]
  24. rolls = [get_roll(1), get_roll(2), get_roll(3)]
  25. for roll in rolls:
  26. has_all_keys = True
  27. for key in keys:
  28. if not key in roll:
  29. has_all_keys = False
  30. self.assertTrue(has_all_keys,
  31. f"roll dict with length {len(roll['result'])} should have all keys")
  32. # injection tests
  33. def test_injection(self):
  34. """Tests if the injection is the same in the output"""
  35. if len(DICE) < 2:
  36. print("Unable to test injection ordering, since too few elements exist")
  37. return
  38. injections = _get_ordered_injection(DICE, [0,1,2,3])
  39. for injection in injections:
  40. roll = get_roll(len(injection), injection)
  41. self.assertEqual(roll["result"], injection,
  42. f"injection {injection} should be the same in the roll result")
  43. def test_injection_fill(self):
  44. """Tests if an underfull injection gets filled up by random numbers"""
  45. injections = _get_ordered_injection(DICE, [0,1,2])
  46. amount = 4
  47. for injection in injections:
  48. roll = get_roll(amount, injection)
  49. self.assertEqual(amount, len(roll["result"]),
  50. f"injected roll result {injection} length should be equal to amount")
  51. def test_injection_overlong(self):
  52. """Tests if an overlong injection will be cut off"""
  53. injection = _get_ordered_injection(DICE, [5])[0]
  54. amount = 4
  55. roll = get_roll(amount, injection)
  56. self.assertEqual(roll["result"], injection[:amount],
  57. "injected overlong roll should be equal after being cut off to the result")
  58. def test_injection_fill_placement(self):
  59. """Tests if a injected underfull injection is correctly placed"""
  60. injections = _get_ordered_injection(DICE, [0,1,2])
  61. amount = 4
  62. for injection in injections:
  63. roll = get_roll(amount, injection)
  64. res = roll["result"][:len(injection)]
  65. self.assertEqual(res, injection,
  66. "beginning of result should be equal to underlong injection")
  67. # failure tests
  68. def test_failure_detection(self):
  69. """Tests if failures are detected correctly.
  70. Failures are if half (rounded up) or more are failure rolls (here: 1)."""
  71. fail = FAILS[0]
  72. non_fail = self.NON_FAILS[0]
  73. if len(FAILS) < 1 and len(self.NON_FAILS) < 1:
  74. print("Not able to test failure detection with no failures or no neutral results/hits")
  75. return
  76. # test fail
  77. roll = get_roll(1, [fail])
  78. self.assertTrue(roll["isFailure"],
  79. "single roll with result {fail} should be a failure according to config")
  80. # test non fail
  81. for res in self.NON_FAILS:
  82. roll = get_roll(1, [res])
  83. self.assertFalse(roll["isFailure"],
  84. f"single roll with result {res} should not be a failure according to config")
  85. # test uneven
  86. for res in [[fail,non_fail,non_fail], [non_fail]*3]:
  87. roll = get_roll(3, res)
  88. self.assertFalse(roll["isFailure"],
  89. f"tripple roll with result {res} should not be a failure")
  90. for res in [[fail]*3, [fail,fail,non_fail]]:
  91. roll = get_roll(3, res)
  92. self.assertTrue(roll["isFailure"],
  93. f"tripple roll with result {res} should be a failure")
  94. # test uneven
  95. for res in [[fail,fail,non_fail,non_fail], [non_fail]*4]:
  96. roll = get_roll(4, res)
  97. self.assertFalse(roll["isFailure"],
  98. f"quad roll with result {res} should not be a failure")
  99. for res in [[fail]*4, [fail,fail,fail,non_fail]]:
  100. roll = get_roll(4, res)
  101. self.assertTrue(roll["isFailure"],
  102. f"quad roll with result {res} should be a failure")
  103. # TODO: test DICE, HITS and FAILS with different kinds of data types
  104. # problem: how to change config dynamically/load dynamically?
  105. # at the moment it tests from the current config only
  106. ### helpers ####
  107. def _get_ordered_injection(dice: list, lens: list) -> list:
  108. """Return a list of lists, which have a unique element at the second position,
  109. eg an amount of 4 with dice = [0,1]:
  110. [0,1,0,0]
  111. """
  112. if len(dice) < 2:
  113. raise Exception("At least two dice entries required.")
  114. injections = []
  115. # create injection
  116. for lst_len in lens:
  117. if lst_len < 1:
  118. injections.append([])
  119. else:
  120. injections.append([dice[0]])
  121. if lst_len > 1:
  122. injections[-1].append(dice[1])
  123. lst_len -= 2 # two numbers were added already
  124. while lst_len > 0:
  125. injections[-1].append(dice[0])
  126. lst_len -= 1
  127. return injections
  128. if __name__ == '__main__':
  129. unittest.main()