import unittest from library import Library, one_book, at_most_books import datetime class TestLibraryAddUsers(unittest.TestCase): def setUp(self): #this is executed before each test case in this class self.lib=Library() self.lib.add_user("Jano") self.lib.add_user("Fero") self.lib.add_book("Book") def test_if_user_does_exist_adduser_returns_false(self): self.assertFalse(self.lib.add_user("Jano")) def test_if_user_does_exist_adduser_returns_false(self): self.assertTrue(self.lib.add_user("Juro")) class TestLibraryBooksAndReservations(unittest.TestCase): def setUp(self): self.lib=Library() self.lib.add_user("Jano") self.lib.add_book("Book1") self.lib.add_book("Book1") self.lib.add_book("Book2") self.lib.reserve_book("Jano", "Book1", datetime.date(2018,1,3), datetime.date(2018,1,7)) self.lib.reserve_book("Jano", "Book1", datetime.date(2018,1,1), datetime.date(2018,1,5)) self.lib.reserve_book("Jano", "Book2", datetime.date(2018,2,1), datetime.date(2018,2,5)) def test_existing_users_can_make_reservation_if_book_is_unbooked(self): self.assertTrue(self.lib.reserve_book("Jano", "Book2", datetime.date(2018,1,1), datetime.date(2018,1,5)) ) def test_if_the_book_is_booked_for_the_dates_returns_false_and_no_booking_is_made(self): self.assertFalse(self.lib.reserve_book("Jano", "Book2", datetime.date(2018,2,5), datetime.date(2018,2,8)) ) self.assertTrue(self.lib.reserve_book("Jano", "Book2", datetime.date(2018,2,6), datetime.date(2018,2,8)) ) def test_if_there_are_k_books_with_the_same_title_you_can_book_it_that_k_times(self): self.assertTrue(self.lib.reserve_book("Jano", "Book1", datetime.date(2018,1,1), datetime.date(2018,1,1)) ) def test_if_there_are_k_books_with_the_same_title_you_can_not_book_it_k_plus_one_times(self): self.assertFalse(self.lib.reserve_book("Jano", "Book1", datetime.date(2018,1,1), datetime.date(2018,1,3)) ) self.assertTrue(self.lib.reserve_book("Jano", "Book1", datetime.date(2017,12,31), datetime.date(2018,1,1)) ) def test_if_user_does_not_exists_return_false_and_reservation_is_not_created(self): self.assertFalse(self.lib.reserve_book("Juro", "Book2", datetime.date(2018,1,5), datetime.date(2018,1,6)) ) self.assertTrue(self.lib.reserve_book("Jano", "Book2", datetime.date(2018,1,5), datetime.date(2018,1,6)) ) def test_if_book_does_not_exists_return_false(self): self.assertFalse(self.lib.reserve_book("Jano", "Non-existing book", datetime.date(2018,1,5), datetime.date(2018,1,6)) ) def test_if_the_books_are_in_wrong_order_return_false(self): self.assertFalse(self.lib.reserve_book("Jano", "Book2", datetime.date(2018,1,6), datetime.date(2018,1,5)) ) def test_you_can_iterate_books(self): books={"Book1":0, "Book2":0} for b in self.lib.books(): books[b]+=1 self.assertEqual(len(books), 2) self.assertEqual(books["Book1"], 2) self.assertEqual(books["Book2"], 1) #Ideally, the method books() should be just a lazily initialized iterable #A test could follow that takes a huge list of books and iterates first elements many times to test the behaviour #Note that such a test is not good for a basic test cuite def test_you_can_iterate_reservations_sorted_by_start_date(self): reservations=[] for r in self.lib.reservations(): reservations.append(r) self.assertEqual(reservations, [ (datetime.date(2018,1,1), datetime.date(2018,1,5), "Book1"), (datetime.date(2018,1,3), datetime.date(2018,1,7), "Book1"), (datetime.date(2018,2,1), datetime.date(2018,2,5), "Book2") ]) #Ideally, the method reservations() should be just a lazily initialized iterable #This might not be easy, Google, Google, Google class TestOneBookDecorator(unittest.TestCase): #onebook decorator can be used to decorate library and its subclases #(provided that the subclass implementation does not break Library functionality) @one_book class OneBookLibrary(Library): pass def setUp(self): self.lib=TestOneBookDecorator.OneBookLibrary() self.lib.add_user("Jano") def test_adding_new_book_returns_true(self): self.assertTrue(self.lib.add_book("Book1")) def test_you_cannot_add_or_reserve_the_same_book_twice(self): self.assertTrue(self.lib.add_book("Book1")) self.assertFalse(self.lib.add_book("Book1")) self.assertTrue(self.lib.add_book("Book2")) books={"Book1":0, "Book2":0} for b in self.lib.books(): books[b]+=1 self.assertEqual(len(books), 2) self.assertEqual(books["Book1"], 1) self.assertEqual(books["Book2"], 1) self.lib.reserve_book("Jano", "Book1", datetime.date(2018,1,3), datetime.date(2018,1,7)) self.assertFalse(self.lib.reserve_book("Jano", "Book1", datetime.date(2018,1,7), datetime.date(2018,1,8))) class TestAtMostBooksDecorator(unittest.TestCase): #onebook decorator can be used to decorate library and its subclases #(provided that the subclass implementation does not break Library functionality) @at_most_books(2) class TwoBookLibrary(Library): pass def setUp(self): self.lib=TestAtMostBooksDecorator.TwoBookLibrary() def test_adding_new_book_returns_true(self): self.assertTrue(self.lib.add_book("Book1")) self.assertTrue(self.lib.add_book("Book1")) def test_you_cannot_add_or_reserve_the_same_book_more_than_k_times(self): self.assertTrue(self.lib.add_book("Book1")) self.assertTrue(self.lib.add_book("Book1")) self.assertFalse(self.lib.add_book("Book1")) self.assertTrue(self.lib.add_book("Book2")) books={"Book1":0, "Book2":0} for b in self.lib.books(): books[b]+=1 self.assertEqual(len(books), 2) self.assertEqual(books["Book1"], 2) self.assertEqual(books["Book2"], 1) #you can run this file by "python3 test_library.py" if __name__ == '__main__': unittest.main()