class TestDB(unittest.TestCase): def setUp(self): self.CuT = Library_DB() self.CuT.close_db() self.CuT.db = Mock() self.patron1 = Patron("Reggie", "Miller", 49, "987654321") self.patron2 = Patron("Todd", "Dodd", 20, "12345") self.patron1.add_borrowed_book("Old Man and the Sea") def test_insert_patron_not_Patron(self): self.assertIsNone(self.CuT.insert_patron(None)) def test_insert_patron_already_inserted(self): self.CuT.retrieve_patron = Mock() self.CuT.retrieve_patron.return_value = self.patron2 self.assertIsNone(self.CuT.insert_patron(self.patron2)) def test_insert_patron_success(self): self.CuT.retrieve_patron = Mock() self.CuT.retrieve_patron.return_value = None self.assertIsNotNone(self.CuT.insert_patron(self.patron2)) def test_get_patron_count(self): self.CuT.db.all.return_value = [] self.assertEqual(0, self.CuT.get_patron_count()) def test_get_all_patrons(self): self.CuT.db.all.return_value = ["test", "filler"] self.assertEqual(["test", "filler"], self.CuT.get_all_patrons()) def test_update_patron_not_Patron(self): self.assertIsNone(self.CuT.update_patron(None)) def test_update_patron_success(self): self.patron2.add_borrowed_book("test") self.CuT.update_patron(self.patron2) self.CuT.db.update.assert_called_once() def test_retrieve_patron_not_found(self): self.CuT.db.search.return_value = None self.assertIsNone(self.CuT.retrieve_patron(None)) def test_retrieve_patron_success(self): self.CuT.db.search.return_value = [{ "fname": "Reggie", "lname": "Miller", "age": 49, "memberID": "987654321", "borrowed_books": [] }] patron = self.CuT.retrieve_patron(self.patron1) self.assertEqual(patron.memberID, self.patron1.memberID) def test_close_db(self): self.CuT.close_db() self.assertTrue(self.CuT.db.close.called) def test_convert_patron_to_db_format(self): self.assertIsNotNone(self.CuT.convert_patron_to_db_format( self.patron1))
class Library: """Class used to represent a library.""" def __init__(self): """Constructor for the Library class.""" self.db = Library_DB() self.api = Books_API() ############################################################################ ################################ API METHODS ############################### ############################################################################ def is_ebook(self, book): """Checks if the book is an e-book. :param book: the title of the book :returns: True if yes, False if not """ ebooks = self.api.get_ebooks(book) book = book.lower() for ebook in ebooks: if book == ebook['title'].lower(): return True return False def get_ebooks_count(self, book): """Gets the number of ebooks for a given book. :param book: the title of the book :returns: the number of ebooks """ ebooks = self.api.get_ebooks(book) ebook_count = 0 for ebook in ebooks: ebook_count += ebook['ebook_count'] return ebook_count def is_book_by_author(self, author, book): """Determines if the book was written by a given author. :param author: the name of the author :param book: the name of the book :returns: True if the book was written by the author, False if not """ results = self.api.books_by_author(author) for result in results: if book.lower() == result.lower(): return True return False def get_languages_for_book(self, book): """Get the available languages for a given book. :param book: the title of the book :returns: the set of languages the book is available in """ books_info = self.api.get_book_info(book) lang_set = set() for book in books_info: if 'language' in book: lang_set.update(book['language']) return lang_set ############################################################################ ################################# DB METHODS ############################### ############################################################################ def register_patron(self, fname, lname, age, memberID): """Registers a Patron with the library and adds them to the database. :param fname: the Patron's first name :param lname: the Patron's last name :param age: the Patron's age :param memberID: the ID of the Patron :returns: None if the Patron is already in the database, else their ID """ patron = Patron(fname, lname, age, memberID) return self.db.insert_patron(patron) def is_patron_registered(self, patron): """Determines if the Patron is already registered in the database. :param patron: the Patron object :returns: True if they are in the database, False if not """ reg_patron = self.db.retrieve_patron(patron.get_memberID()) if reg_patron: return True return False def borrow_book(self, book, patron): """Borrows a book for a Patron. :param book: the title of the book :param patron: the Patron object """ patron.add_borrowed_book(book.lower()) self.db.update_patron(patron) def return_borrowed_book(self, book, patron): """Returns a borrowed book for a Patron. :param book: the title of the book :param patron: the Patron object """ patron.return_borrowed_book(book.lower()) self.db.update_patron(patron) def is_book_borrowed(self, book, patron): """Determines if the Patron has borrowed a given book. :param book: the title of the book :param patron: the Patron object :returns: True if the Patron has borrowed the book, False if not """ borrowed_books = patron.get_borrowed_books() return book.lower() in borrowed_books
class Library: def __init__(self): self.db = Library_DB() self.api = Books_API() ############################################################################ ################################ API METHODS ############################### ############################################################################ def is_ebook(self, book): ebooks = self.api.get_ebooks(book) book = book.lower() for ebook in ebooks: if book == ebook['title'].lower(): return True return False def get_ebooks_count(self, book): ebooks = self.api.get_ebooks(book) ebook_count = 0 for ebook in ebooks: ebook_count += ebook['ebook_count'] return ebook_count def is_book_by_author(self, author, book): results = self.api.books_by_author(author) for result in results: if book.lower() == result.lower(): return True return False def get_languages_for_book(self, book): books_info = self.api.get_book_info(book) lang_set = set() for book in books_info: if 'language' in book: lang_set.update(book['language']) return lang_set ############################################################################ ################################# DB METHODS ############################### ############################################################################ def register_patron(self, fname, lname, age, memberID): patron = Patron(fname, lname, age, memberID) return self.db.insert_patron(patron) def is_patron_registered(self, patron): reg_patron = self.db.retrieve_patron(patron.get_memberID()) if reg_patron: return True return False def borrow_book(self, book, patron): patron.add_borrowed_book(book.lower()) self.db.update_patron(patron) def return_borrowed_book(self, book, patron): patron.return_borrowed_book(book.lower()) self.db.update_patron(patron) def is_book_borrowed(self, book, patron): borrowed_books = patron.get_borrowed_books() return book.lower() in borrowed_books
class TestLibraryDBInterface(unittest.TestCase): CuT = Library_DB() CuT.close_db() def tearDown(self): if os.path.exists('db.json'): os.remove('db.json') def test_insert_patron_not_patron(self): self.assertEqual(None, self.CuT.insert_patron(0)) def test_insert_patron_mock_patron_not_in_db(self): mock_patron = Mock(Patron) mock_patron.get_memberid = Mock() mock_patron.get_memberid.return_value = ('1') self.CuT = Library_DB() self.CuT.close_db() self.CuT.db = Mock() self.CuT.db.search = Mock() self.CuT.db.search.return_value = None # patron is not in db self.CuT.db.insert = Mock() self.CuT.db.insert.return_value = 1 self.CuT.insert_patron(mock_patron) self.CuT.db.insert.assert_called_once( ) # patron is inserted if this happens def test_insert_patron_mock_patron_in_db(self): mock_patron = Mock(Patron) mock_patron.get_memberid = Mock() mock_patron.get_memberid.return_value = ('1') self.CuT.db = Mock() self.CuT.db.search = Mock() self.CuT.db.search.return_value = mock_patron # patron is in db self.CuT.db.insert = Mock() self.CuT.db.insert.return_value = 1 self.CuT.retrieve_patron = Mock() self.CuT.retrieve_patron.return_value = mock_patron # Can't subscript a mock so do this for now # and test retrieve_patron method later self.CuT.insert_patron(mock_patron) self.CuT.db.insert.assert_not_called( ) # patron is not inserted because patron is in db def test_get_patron_count(self): self.CuT.db = Mock() self.CuT.db.all = Mock() self.CuT.db.all.return_value = [] # list of patrons in db self.assertEqual(0, self.CuT.get_patron_count()) def test_get_patron_count_multiple(self): mock_patron = Mock(Patron) mock_patron.get_memberid = Mock() self.CuT.db = Mock() self.CuT.db.all = Mock() self.CuT.db.all.return_value = [mock_patron, mock_patron] # list of patrons in db self.assertEqual(2, self.CuT.get_patron_count()) def test_get_all_patrons(self): self.CuT.db = Mock() self.CuT.db.all = Mock() self.CuT.db.all.return_value = [] # list of patrons in db self.assertEqual([], self.CuT.get_all_patrons()) def test_get_all_patrons_multiple(self): mock_patron = Mock(Patron) mock_patron.get_memberid = Mock() self.CuT.db = Mock() self.CuT.db.all = Mock() self.CuT.db.all.return_value = [mock_patron, mock_patron] # list of patrons in db self.assertEqual([mock_patron, mock_patron], self.CuT.get_all_patrons()) def test_update_patron_not_patron(self): self.assertEqual(None, self.CuT.update_patron(0)) def test_update_patron(self): mock_patron = Mock(Patron) mock_patron.get_memberid = Mock() self.CuT.db = Mock() self.CuT.convert_patron_to_db_format = Mock() self.CuT.convert_patron_to_db_format.return_value = mock_patron self.CuT.db.update = Mock() self.CuT.update_patron(mock_patron) self.CuT.db.update.assert_called_once() def test_retrieve_patron(self): self.CuT = Library_DB() self.CuT.close_db() self.CuT.db = Mock() self.CuT.db.search = Mock() self.CuT.db.search.return_value = False self.assertEqual(None, self.CuT.retrieve_patron(1)) def test_close_db(self): self.CuT.db = Mock() self.CuT.db.close = Mock() self.CuT.close_db() self.CuT.db.close.assert_called_once()