213 lines
9.3 KiB
Python
213 lines
9.3 KiB
Python
import unittest
|
|
import pytest
|
|
|
|
|
|
try:
|
|
from classes import Alien
|
|
except ImportError as import_fail:
|
|
# pylint: disable=raise-missing-from
|
|
raise ImportError("\n\nMISSING CLASS --> We tried to import the 'Alien' class from "
|
|
"your classes.py file, but could not find it."
|
|
"Did you misname or forget to create it?") from None
|
|
|
|
try:
|
|
from classes import new_aliens_collection
|
|
except ImportError as err:
|
|
raise ImportError("\n\nMISSING FUNCTION --> We tried to import the "
|
|
"new_aliens_collection() function "
|
|
"from your classes.py file, but could not find it. "
|
|
"Did you misname or forget to create it?") from None
|
|
|
|
|
|
class ClassesTest(unittest.TestCase):
|
|
|
|
@pytest.mark.task(taskno=1)
|
|
def test_alien_has_correct_initial_coordinates(self):
|
|
"""Test that the Alien class gets correctly initialised."""
|
|
|
|
alien = Alien(2, -1)
|
|
error_message = (f'Created a new Alien by calling Alien(2, -1). '
|
|
f'The Alien was initialized to position '
|
|
f'{(alien.x_coordinate, alien.y_coordinate)}, but the tests expected '
|
|
f'the object to be at position (2, -1)')
|
|
|
|
self.assertEqual((2, -1), (alien.x_coordinate, alien.y_coordinate), msg=error_message)
|
|
|
|
@pytest.mark.task(taskno=1)
|
|
def test_alien_has_health(self):
|
|
alien = Alien(0, 0)
|
|
error_message = (f'Created a new Alien by calling Alien(0, 0). '
|
|
f'The new Alien has a health of {alien.health}, '
|
|
f'but the tests expect health = 3')
|
|
|
|
self.assertEqual(3, alien.health, msg=error_message)
|
|
|
|
@pytest.mark.task(taskno=1)
|
|
def test_alien_instance_variables(self):
|
|
"""Test instance variables are unique to specific instances."""
|
|
|
|
alien_one = Alien(-8, -1)
|
|
alien_two = Alien(2, 5)
|
|
|
|
coord_x_error = (f'Created two new Aliens by assigning '
|
|
f'alien_one = Alien(-8, -1) and alien_two = Alien(2, 5). '
|
|
f'Both Aliens x coordinates were {alien_two.x_coordinate}, '
|
|
f'but the tests expect alien_one and alien_two to have '
|
|
f'different x positions.')
|
|
|
|
coord_y_error = (f'Created two new Aliens by assigning '
|
|
f'alien_one = Alien(-8, -1) and alien_two = Alien(2, 5). '
|
|
f'Both Aliens y coordinates were {alien_two.y_coordinate}, '
|
|
f'but the tests expect alien_one and alien_two to have '
|
|
f'different y positions.')
|
|
|
|
self.assertFalse(alien_one.x_coordinate == alien_two.x_coordinate, msg=coord_x_error)
|
|
self.assertFalse(alien_one.y_coordinate == alien_two.y_coordinate, msg=coord_y_error)
|
|
|
|
|
|
@pytest.mark.task(taskno=2)
|
|
def test_alien_hit_method(self):
|
|
"""Test class methods work as specified.
|
|
|
|
There are two valid interpretations for this method/task.
|
|
`self.health -= 1` and `self.health = max(0, self.health - 1)`
|
|
The tests for this task reflect this ambiguity.
|
|
|
|
"""
|
|
|
|
test_data = [1, 2, 3, 4, 5, 6]
|
|
result_data = [(2,), (1,), (0,), (0, -1), (0, -2), (0, -3)]
|
|
|
|
for variant, (iterations, expected) in enumerate(zip(test_data, result_data), start=1):
|
|
alien = Alien(2, 2)
|
|
|
|
with self.subTest(f'variation #{variant}',
|
|
iterations=iterations,
|
|
expected=expected):
|
|
|
|
for _ in range(iterations):
|
|
alien.hit()
|
|
|
|
error_message = (f'Called hit() {iterations} time(s) '
|
|
f'on a newly created Alien. The Aliens health '
|
|
f'is now {alien.health}, but the tests expected '
|
|
f'it to be in {expected} after decrementing 1 health '
|
|
f'point {iterations} time(s).')
|
|
|
|
self.assertIn(alien.health, expected, msg=error_message)
|
|
|
|
|
|
@pytest.mark.task(taskno=3)
|
|
def test_alien_is_alive_method(self):
|
|
alien = Alien(0, 1)
|
|
|
|
alive_error = ('Created a new Alien and called hit(). '
|
|
'The function is_alive() is returning False (dead) '
|
|
'while alien.health is greater than 0.')
|
|
|
|
dead_error = ('Created a new Alien and called hit(). '
|
|
'The function is_alive() is returning True (alive) '
|
|
'while alien.health is less than or equal to 0.')
|
|
|
|
for _ in range(5):
|
|
alien.hit()
|
|
if alien.health > 0:
|
|
self.assertTrue(alien.is_alive(), msg=alive_error)
|
|
else:
|
|
self.assertFalse(alien.is_alive(), msg=dead_error)
|
|
|
|
@pytest.mark.task(taskno=4)
|
|
def test_alien_teleport_method(self):
|
|
alien = Alien(0, 0)
|
|
alien.teleport(-1, -4)
|
|
|
|
error_message = ('Called alien.teleport(-1,-4) on a newly created Alien. '
|
|
'The Alien was found at position '
|
|
f'{(alien.x_coordinate, alien.y_coordinate)}, but the '
|
|
'tests expected it at position (-1, -4).')
|
|
|
|
self.assertEqual((-1, -4), (alien.x_coordinate, alien.y_coordinate), msg=error_message)
|
|
|
|
@pytest.mark.task(taskno=5)
|
|
def test_alien_collision_detection_method(self):
|
|
alien = Alien(7, 3)
|
|
error_message = ('Created a new Alien at (7,3) and called '
|
|
'alien.collision_detection(Alien(7, 2)). '
|
|
f'The method returned {alien.collision_detection(Alien(7, 2))}, '
|
|
'but the tests expected None. ')
|
|
|
|
self.assertIsNone(alien.collision_detection(Alien(7, 2)), msg=error_message)
|
|
|
|
|
|
@pytest.mark.task(taskno=6)
|
|
def test_alien_class_variable(self):
|
|
"""Test class attribute/variables are identical across instances."""
|
|
|
|
alien_one, alien_two = Alien(0, 2), Alien(-6, -1)
|
|
Alien.health = 6
|
|
|
|
created_error_message = ('Created two new Aliens and requested the '
|
|
'total_aliens_created attribute for each one. '
|
|
f'Received {alien_one.total_aliens_created, alien_two.total_aliens_created} '
|
|
f'for total_aliens_created, but the tests expect '
|
|
f'the class attributes for each newly created Alien to be identical. ')
|
|
|
|
health_error_message = ('Created two new Aliens and requested the '
|
|
f'health attribute for each one. Received {alien_one.health, alien_two.health} '
|
|
'for health, but the tests expect the class '
|
|
'attributes for each newly created Alien to be identical. ')
|
|
|
|
self.assertEqual(alien_two.total_aliens_created,
|
|
alien_one.total_aliens_created,
|
|
msg=created_error_message)
|
|
|
|
self.assertEqual(alien_two.health,
|
|
alien_one.health,
|
|
msg=health_error_message)
|
|
|
|
@pytest.mark.task(taskno=6)
|
|
def test_alien_total_aliens_created(self):
|
|
"""Test total_aliens_created class variable increments upon object instantiation."""
|
|
|
|
Alien.total_aliens_created = 0
|
|
aliens = [Alien(-2, 6)]
|
|
|
|
error_message = ('Created a new Alien and called total_aliens_created for it. '
|
|
f'{aliens[0].total_aliens_created} was returned, but '
|
|
'the tests expected that total_aliens_created would equal 1.')
|
|
|
|
self.assertEqual(1, aliens[0].total_aliens_created, msg=error_message)
|
|
|
|
aliens.append(Alien(3, 5))
|
|
aliens.append(Alien(-5, -5))
|
|
|
|
def error_text(alien, variable):
|
|
return ('Created two additional Aliens for the session.'
|
|
f"Alien number {alien}'s total_aliens_created variable "
|
|
f"is equal to {variable}, but the tests expected all "
|
|
'total_aliens_created variables for all instances to be '
|
|
'equal to number of alien instances created (i.e. 3).')
|
|
|
|
self.assertEqual(3, aliens[0].total_aliens_created, msg=error_text(1, aliens[0]))
|
|
self.assertEqual(3, aliens[1].total_aliens_created, msg=error_text(2, aliens[1]))
|
|
self.assertEqual(3, aliens[2].total_aliens_created, msg=error_text(3, aliens[2]))
|
|
|
|
@pytest.mark.task(taskno=7)
|
|
def test_new_aliens_collection(self):
|
|
"""Test that the user knows how to create objects themselves."""
|
|
|
|
test_data = [(-2, 6), (1, 5), (-4, -3)]
|
|
actual_result = new_aliens_collection(test_data)
|
|
|
|
error_message = "new_aliens_collection() must return a list of Alien objects."
|
|
|
|
for obj in actual_result:
|
|
self.assertIsInstance(obj, Alien, msg=error_message)
|
|
|
|
for position, obj in zip(test_data, actual_result):
|
|
position_error = (f'After calling new_aliens_collection({test_data}), '
|
|
f'found {obj} initialized to position {(obj.x_coordinate, obj.y_coordinate)}, '
|
|
f'but the tests expected {obj} to be at position {position} instead.')
|
|
|
|
self.assertEqual(position, (obj.x_coordinate, obj.y_coordinate), msg=position_error)
|