from problem3solution import *
import random
import unittest


# This is one of the very few times I'm ever willing to say
# "from X import *", because it's not unreasonable for a test
# module to know everything about the module it's testing;
# these two modules are, by their nature, symbiotic.


class StudentTest(unittest.TestCase):
    def test_has_name_given_when_created(self):
        student1 = Student('Alex', 12345)
        student2 = Student('Boo', 34567)

        self.assertEqual(student1.name(), 'Alex')
        self.assertEqual(student2.name(), 'Boo')


    def test_has_id_given_when_created(self):
        student1 = Student('Alex', 12345)
        student2 = Student('Boo', 34567)

        self.assertEqual(student1.student_id(), 12345)
        self.assertEqual(student2.student_id(), 34567)



class ClubTest(unittest.TestCase):
    def setUp(self):
        self._club = Club()
        self._student_ids = list(range(1000, 9999))
        random.shuffle(self._student_ids)

        
    def test_new_clubs_have_no_students(self):
        self.assertEqual(self._club.number_of_students(), 0)


    def test_after_adding_student__has_1_student(self):
        self._club.add_student(self._create_test_student())
        self.assertEqual(self._club.number_of_students(), 1)


    def test_continuing_to_add_students_means_more_students(self):
        for student_count in range(1, 101):
            self._club.add_student(self._create_test_student())
            self.assertEqual(self._club.number_of_students(), student_count)


    def test_no_students_are_members_before_adding_any(self):
        self.assertFalse(self._club.is_member(12345))
        self.assertFalse(self._club.is_member(99999))


    def test_students_are_members_after_adding(self):
        student1 = self._create_test_student()
        student2 = self._create_test_student()

        self.assertFalse(self._club.is_member(student1.student_id()))
        self.assertFalse(self._club.is_member(student2.student_id()))

        self._club.add_student(student1)

        self.assertTrue(self._club.is_member(student1.student_id()))
        self.assertFalse(self._club.is_member(student2.student_id()))

        self._club.add_student(student2)

        self.assertTrue(self._club.is_member(student1.student_id()))
        self.assertTrue(self._club.is_member(student2.student_id()))


    def test_cannot_get_student_before_adding_any(self):
        with self.assertRaises(ClubMembershipError):
            self._club.get_student_by_id(12345)

        with self.assertRaises(ClubMembershipError):
            self._club.get_student_by_id(99999)


    def test_can_get_student_after_adding(self):
        student1 = self._create_test_student()
        student2 = self._create_test_student()

        self._club.add_student(student1)

        self.assertEqual(self._club.get_student_by_id(student1.student_id()), student1)

        self._club.add_student(student2)

        self.assertEqual(self._club.get_student_by_id(student2.student_id()), student2)


    def test_cannot_add_student_when_id_already_in_club(self):
        student1 = self._create_test_student()

        self._club.add_student(student1)

        with self.assertRaises(ClubMembershipError):
            self._club.add_student(student1)


    def _create_test_student(self):
        name = ''.join(random.choices('ABCDEFGHIJKLMNOPQRSTUVWXYZ', k = 8))
        return Student(name, self._student_ids.pop())



if __name__ == '__main__':
    unittest.main()
