diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..b488657 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +name: Python CI + +on: + push: + branches: [ "**" ] + pull_request: + branches: [ "main" ] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.9] + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run tests with pytest + run: | + pytest \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/LibrarySystem1.iml b/.idea/LibrarySystem1.iml new file mode 100644 index 0000000..6fb6f82 --- /dev/null +++ b/.idea/LibrarySystem1.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..8a08999 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..0b47a07 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/__pycache__/book.cpython-311.pyc b/__pycache__/book.cpython-311.pyc new file mode 100644 index 0000000..f2d4409 Binary files /dev/null and b/__pycache__/book.cpython-311.pyc differ diff --git a/__pycache__/library.cpython-311.pyc b/__pycache__/library.cpython-311.pyc new file mode 100644 index 0000000..4dd958b Binary files /dev/null and b/__pycache__/library.cpython-311.pyc differ diff --git a/book.py b/book.py new file mode 100644 index 0000000..59854ad --- /dev/null +++ b/book.py @@ -0,0 +1,14 @@ +class Book: + def __init__(self, title, author): + self.title = title + self.author = author + self.available = True + + def borrow(self): + if not self.available: + return False + self.available = False + return True + + def return_book(self): + self.available = True \ No newline at end of file diff --git a/library.py b/library.py new file mode 100644 index 0000000..4128481 --- /dev/null +++ b/library.py @@ -0,0 +1,27 @@ +from book import Book + +class Library: + def __init__(self): + self.books = [] + + def add_book(self, title, author): + self.books.append(Book(title, author)) + + def is_available(self, title): + for book in self.books: + if book.title == title: + return book.available + return False + + def borrow_book(self, title): + for book in self.books: + if book.title == title: + return book.borrow() + return False + + def return_book(self, title): + for book in self.books: + if book.title == title: + book.return_book() + return True + return False diff --git a/main.py b/main.py index 8b13789..cbbc6b6 100644 --- a/main.py +++ b/main.py @@ -1 +1,50 @@ + +from library import Library + +def main(): + lib = Library() + + print("\n📚 Welcome to the Library System") + + # Add books to the library + lib.add_book("1984", "George Orwell") + lib.add_book("The Hobbit", "J.R.R. Tolkien") + + print("\n📖 Books Added:") + for book in lib.books: + print(f"- {book.title} by {book.author} (Available: {book.available})") + + # Check availability + print(f"\n🔍 Is '1984' available? {lib.is_available('1984')}") + + # Borrow a book + print("\n📥 Borrowing '1984'...") + success = lib.borrow_book("1984") + print(f"Borrowed: {success}") + print(f"Available now? {lib.is_available('1984')}") + + # Try borrowing it again + print("\n📥 Trying to borrow '1984' again...") + success = lib.borrow_book("1984") + print(f"Borrowed: {success}") + + # Return the book + print("\n📤 Returning '1984'...") + returned = lib.return_book("1984") + print(f"Returned: {returned}") + print(f"Available now? {lib.is_available('1984')}") + + # Try returning again (already available) + print("\n📤 Returning '1984' again...") + returned = lib.return_book("1984") + print(f"Returned: {returned}") + + # Borrow a non-existent book + print("\n📥 Borrowing 'Unknown Book'...") + success = lib.borrow_book("Unknown Book") + print(f"Borrowed: {success}") + +if __name__ == "__main__": + main() + diff --git a/requirments.txt b/requirments.txt new file mode 100644 index 0000000..bad3131 --- /dev/null +++ b/requirments.txt @@ -0,0 +1,3 @@ +pytest +requests +flask \ No newline at end of file diff --git a/ci.yml b/tests/__init__.py similarity index 100% rename from ci.yml rename to tests/__init__.py diff --git a/tests/__pycache__/__init__.cpython-311.pyc b/tests/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..d379894 Binary files /dev/null and b/tests/__pycache__/__init__.cpython-311.pyc differ diff --git a/tests/__pycache__/test_book.cpython-311-pytest-8.3.5.pyc b/tests/__pycache__/test_book.cpython-311-pytest-8.3.5.pyc new file mode 100644 index 0000000..a400981 Binary files /dev/null and b/tests/__pycache__/test_book.cpython-311-pytest-8.3.5.pyc differ diff --git a/tests/__pycache__/test_library.cpython-311-pytest-8.3.5.pyc b/tests/__pycache__/test_library.cpython-311-pytest-8.3.5.pyc new file mode 100644 index 0000000..40b157e Binary files /dev/null and b/tests/__pycache__/test_library.cpython-311-pytest-8.3.5.pyc differ diff --git a/tests/test_book.py b/tests/test_book.py new file mode 100644 index 0000000..384ba99 --- /dev/null +++ b/tests/test_book.py @@ -0,0 +1,30 @@ +from book import Book + +def test_initialization(): + """Test 1: Initialization — title, author, and availability set correctly""" + book = Book("Clean Code", "Robert Cecil Martin") + assert book.title == "Clean Code" + assert book.author == "Robert Cecil Martin" + assert book.available is True + +def test_borrow_when_available(): + """Test 2: Borrow when available — borrow() returns True, sets available to False""" + book = Book("Clean Code", "Robert Cecil Martin") + result = book.borrow() + assert result is True + assert book.available is False + +def test_borrow_when_not_available(): + """Test 3: Borrow when not available — borrow() returns False, available remains False""" + book = Book("Clean Code", "Robert Cecil Martin") + book.borrow() # First borrow + result = book.borrow() # Try borrowing again + assert result is False + assert book.available is False + +def test_return_book(): + """Test 4: Return book — return_book() sets available to True""" + book = Book("Clean Code", "Robert Cecil Martin") + book.borrow() + book.return_book() + assert book.available is True diff --git a/tests/test_library.py b/tests/test_library.py new file mode 100644 index 0000000..aeba356 --- /dev/null +++ b/tests/test_library.py @@ -0,0 +1,87 @@ +from library import Library + +# 1. Library Initialization +def test_library_initialization(): + """ + Test: Library should initialize with an empty book list. + """ + lib = Library() + assert isinstance(lib.books, list) + assert len(lib.books) == 0 + +# 2. Add book +def test_add_book(): + """ + Test: Add book to the library. + - Book is added to the list with correct details. + - Book is initially available. + """ + lib = Library() + lib.add_book("1984", "George Orwell") + assert len(lib.books) == 1 + book = lib.books[0] + assert book.title == "1984" + assert book.author == "George Orwell" + assert book.available is True + +# 3. Check availability - exists +def test_is_available_true(): + lib = Library() + lib.add_book("Dune", "Frank Herbert") + assert lib.is_available("Dune") is True + +# 4. Check availability - doesn’t exist +def test_is_available_false_for_nonexistent_book(): + lib = Library() + assert lib.is_available("Nonexistent") is False + +# 5. Borrow book - available +def test_borrow_book_available(): + lib = Library() + lib.add_book("Clean Code", "Robert Martin") + result = lib.borrow_book("Clean Code") + assert result is True + assert lib.books[0].available is False + +# 6. Borrow book - already borrowed +def test_borrow_book_already_borrowed(): + lib = Library() + lib.add_book("Clean Code", "Robert Martin") + lib.borrow_book("Clean Code") + result = lib.borrow_book("Clean Code") + assert result is False + assert lib.books[0].available is False + +# 7. Borrow book - not in library +def test_borrow_book_not_in_library(): + lib = Library() + result = lib.borrow_book("Unknown Book") + assert result is False + +# 8. Return book - valid +def test_return_book_valid(): + lib = Library() + lib.add_book("Refactoring", "Martin Fowler") + lib.borrow_book("Refactoring") + result = lib.return_book("Refactoring") + assert result is True + assert lib.books[0].available is True + +# 9. Return book - doesn’t exist +def test_return_book_not_in_library(): + lib = Library() + result = lib.return_book("Nonexistent") + assert result is False + +# 10. Return book - already available +def test_return_book_already_available(): + """ + Returning a book that's already available: + - Should return True. + - Should not break logic. + """ + lib = Library() + lib.add_book("Domain-Driven Design", "Eric Evans") + result = lib.return_book("Domain-Driven Design") + assert result is True + assert lib.books[0].available is True