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