|
9 | 9 | from axelrod import DefaultGame, MockPlayer, Player, simulate_play
|
10 | 10 | from axelrod.player import get_state_distribution_from_history
|
11 | 11 |
|
| 12 | +from hypothesis import given |
| 13 | +from axelrod.tests.property import strategy_lists |
12 | 14 |
|
13 | 15 | C, D = axelrod.Actions.C, axelrod.Actions.D
|
14 | 16 |
|
@@ -150,6 +152,148 @@ def test_clone(self):
|
150 | 152 | self.assertEqual(len(player1.history), turns)
|
151 | 153 | self.assertEqual(player1.history, player2.history)
|
152 | 154 |
|
| 155 | + def test_equality(self): |
| 156 | + """Test the equality method for some bespoke cases""" |
| 157 | + # Check repr |
| 158 | + p1 = axelrod.Cooperator() |
| 159 | + p2 = axelrod.Cooperator() |
| 160 | + self.assertEqual(p1, p2) |
| 161 | + p1.__repr__ = lambda: "John Nash" |
| 162 | + self.assertNotEqual(p1, p2) |
| 163 | + |
| 164 | + # Check attributes |
| 165 | + p1 = axelrod.Cooperator() |
| 166 | + p2 = axelrod.Cooperator() |
| 167 | + p1.test = "29" |
| 168 | + self.assertNotEqual(p1, p2) |
| 169 | + |
| 170 | + p1 = axelrod.Cooperator() |
| 171 | + p2 = axelrod.Cooperator() |
| 172 | + p2.test = "29" |
| 173 | + self.assertNotEqual(p1, p2) |
| 174 | + |
| 175 | + p1.test = "29" |
| 176 | + self.assertEqual(p1, p2) |
| 177 | + |
| 178 | + # Check that attributes of both players are tested. |
| 179 | + p1.another_attribute = [1, 2, 3] |
| 180 | + self.assertNotEqual(p1, p2) |
| 181 | + p2.another_attribute = [1, 2, 3] |
| 182 | + self.assertEqual(p1, p2) |
| 183 | + |
| 184 | + p2.another_attribute_2 = {1: 2} |
| 185 | + self.assertNotEqual(p1, p2) |
| 186 | + p1.another_attribute_2 = {1: 2} |
| 187 | + self.assertEqual(p1, p2) |
| 188 | + |
| 189 | + def test_equality_for_numpy_array(self): |
| 190 | + """Check numpy array attribute (a special case)""" |
| 191 | + p1 = axelrod.Cooperator() |
| 192 | + p2 = axelrod.Cooperator() |
| 193 | + |
| 194 | + p1.array = np.array([0, 1]) |
| 195 | + p2.array = np.array([0, 1]) |
| 196 | + self.assertEqual(p1, p2) |
| 197 | + |
| 198 | + p2.array = np.array([1, 0]) |
| 199 | + self.assertNotEqual(p1, p2) |
| 200 | + |
| 201 | + def test_equality_for_generator(self): |
| 202 | + """Test equality works with generator attribute and that the generator |
| 203 | + attribute is not altered during checking of equality""" |
| 204 | + p1 = axelrod.Cooperator() |
| 205 | + p2 = axelrod.Cooperator() |
| 206 | + |
| 207 | + # Check that players are equal with generator |
| 208 | + p1.generator = (i for i in range(10)) |
| 209 | + p2.generator = (i for i in range(10)) |
| 210 | + self.assertEqual(p1, p2) |
| 211 | + |
| 212 | + # Check state of one generator (ensure it hasn't changed) |
| 213 | + n = next(p2.generator) |
| 214 | + self.assertEqual(n, 0) |
| 215 | + |
| 216 | + # Players are no longer equal (one generator has changed) |
| 217 | + self.assertNotEqual(p1, p2) |
| 218 | + |
| 219 | + # Check that internal generator object has not been changed for either |
| 220 | + # player after latest equal check. |
| 221 | + self.assertEqual(list(p1.generator), list(range(10))) |
| 222 | + self.assertEqual(list(p2.generator), list(range(1, 10))) |
| 223 | + |
| 224 | + # Check that type is generator |
| 225 | + self.assertIsInstance(p2.generator, types.GeneratorType) |
| 226 | + |
| 227 | + def test_equality_for_cycle(self): |
| 228 | + """Test equality works with cycle attribute and that the cycle attribute |
| 229 | + is not altered during checking of equality""" |
| 230 | + # Check cycle attribute (a special case) |
| 231 | + p1 = axelrod.Cooperator() |
| 232 | + p2 = axelrod.Cooperator() |
| 233 | + |
| 234 | + # Check that players are equal with cycle |
| 235 | + p1.cycle = itertools.cycle(range(10)) |
| 236 | + p2.cycle = itertools.cycle(range(10)) |
| 237 | + self.assertEqual(p1, p2) |
| 238 | + |
| 239 | + # Check state of one generator (ensure it hasn't changed) |
| 240 | + n = next(p2.cycle) |
| 241 | + self.assertEqual(n, 0) |
| 242 | + |
| 243 | + # Players are no longer equal (one generator has changed) |
| 244 | + self.assertNotEqual(p1, p2) |
| 245 | + |
| 246 | + # Check that internal cycle object has not been changed for either |
| 247 | + # player after latest not equal check. |
| 248 | + self.assertEqual(next(p1.cycle), 0) |
| 249 | + self.assertEqual(next(p2.cycle), 1) |
| 250 | + |
| 251 | + # Check that type is cycle |
| 252 | + self.assertIsInstance(p2.cycle, itertools.cycle) |
| 253 | + |
| 254 | + def test_equality_on_init(self): |
| 255 | + """Test instances of all strategies are equal on init""" |
| 256 | + for s in axelrod.strategies: |
| 257 | + p1, p2 = s(), s() |
| 258 | + # Check three times (so testing equality doesn't change anything) |
| 259 | + self.assertEqual(p1, p2) |
| 260 | + self.assertEqual(p1, p2) |
| 261 | + self.assertEqual(p1, p2) |
| 262 | + |
| 263 | + def test_equality_with_player_as_attributes(self): |
| 264 | + """Test for a strange edge case where players have pointers to each |
| 265 | + other""" |
| 266 | + p1 = axelrod.Cooperator() |
| 267 | + p2 = axelrod.Cooperator() |
| 268 | + |
| 269 | + # If pointing at each other |
| 270 | + p1.player = p2 |
| 271 | + p2.player = p1 |
| 272 | + self.assertEqual(p1, p2) |
| 273 | + |
| 274 | + # Still checking other attributes. |
| 275 | + p1.test_attribute = "29" |
| 276 | + self.assertNotEqual(p1, p2) |
| 277 | + |
| 278 | + # If pointing at same strategy instances |
| 279 | + p1.player = axelrod.Cooperator() |
| 280 | + p2.player = axelrod.Cooperator() |
| 281 | + p2.test_attribute = "29" |
| 282 | + self.assertEqual(p1, p2) |
| 283 | + |
| 284 | + |
| 285 | + # If pointing at different strategy instances |
| 286 | + p1.player = axelrod.Cooperator() |
| 287 | + p2.player = axelrod.Defector() |
| 288 | + self.assertNotEqual(p1, p2) |
| 289 | + |
| 290 | + # If different strategies pointing at same strategy instances |
| 291 | + p3 = axelrod.Defector() |
| 292 | + p1.player = axelrod.Cooperator() |
| 293 | + p3.player = axelrod.Cooperator() |
| 294 | + self.assertNotEqual(p1, p3) |
| 295 | + |
| 296 | + |
153 | 297 | def test_init_params(self):
|
154 | 298 | """Tests player correct parameters signature detection."""
|
155 | 299 | self.assertEqual(self.player.init_params(), {})
|
@@ -285,41 +429,14 @@ def test_reset_history_and_attributes(self):
|
285 | 429 | player.play(opponent)
|
286 | 430 |
|
287 | 431 | player.reset()
|
288 |
| - self.assertEqual(len(player.history), 0) |
289 |
| - self.assertEqual(player.cooperations, 0) |
290 |
| - self.assertEqual(player.defections, 0) |
291 |
| - self.assertEqual(player.state_distribution, dict()) |
292 |
| - |
293 |
| - self.attribute_equality_test(player, clone) |
| 432 | + self.assertEqual(player, clone) |
294 | 433 |
|
295 | 434 | def test_reset_clone(self):
|
296 | 435 | """Make sure history resetting with cloning works correctly, regardless
|
297 | 436 | if self.test_reset() is overwritten."""
|
298 | 437 | player = self.player()
|
299 | 438 | clone = player.clone()
|
300 |
| - self.attribute_equality_test(player, clone) |
301 |
| - |
302 |
| - def attribute_equality_test(self, player, clone): |
303 |
| - """A separate method to test equality of attributes. This method can be |
304 |
| - overwritten in certain cases. |
305 |
| -
|
306 |
| - This method checks that all the attributes of `player` and `clone` are |
307 |
| - the same which is used in the test of the cloning and the resetting. |
308 |
| - """ |
309 |
| - |
310 |
| - for attribute, reset_value in player.__dict__.items(): |
311 |
| - original_value = getattr(clone, attribute) |
312 |
| - |
313 |
| - if isinstance(reset_value, np.ndarray): |
314 |
| - self.assertTrue(np.array_equal(reset_value, original_value), |
315 |
| - msg=attribute) |
316 |
| - |
317 |
| - elif isinstance(reset_value, types.GeneratorType) or isinstance(reset_value, itertools.cycle): |
318 |
| - for _ in range(10): |
319 |
| - self.assertEqual(next(reset_value), |
320 |
| - next(original_value), msg=attribute) |
321 |
| - else: |
322 |
| - self.assertEqual(reset_value, original_value, msg=attribute) |
| 439 | + self.assertEqual(player, clone) |
323 | 440 |
|
324 | 441 | def test_clone(self):
|
325 | 442 | # Test that the cloned player produces identical play
|
|
0 commit comments