-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_api.py
More file actions
149 lines (113 loc) · 4.97 KB
/
test_api.py
File metadata and controls
149 lines (113 loc) · 4.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"""Tests for the FastAPI REST API."""
import pytest
from fastapi.testclient import TestClient
# Import the app and the Library class
from api import app
from library import Library
import config
@pytest.fixture
def client(monkeypatch, tmp_path):
"""
This fixture creates a temporary, isolated environment for each test function.
1. `tmp_path`: A pytest fixture that creates a unique temporary directory.
2. `monkeypatch`: A pytest fixture to safely modify the behavior of our code for tests.
"""
# Define the path for a temporary library file inside the temp directory
test_library_path = tmp_path / "test_library.json"
# Create an empty library file to start fresh
test_library_path.write_text("[]", encoding="utf-8")
# Patch the config to use the test file
monkeypatch.setattr(config, 'LIBRARY_FILE', str(test_library_path))
# The 'with' statement ensures FastAPI's lifespan events run correctly
# for a clean startup and shutdown within the test.
with TestClient(app) as c:
yield c
# All tests now take 'client' as an argument, which provides the isolated environment.
def test_list_all_books_empty(client):
"""Test listing books when the library is empty."""
response = client.get("/books")
assert response.status_code == 200
assert response.json() == []
def test_add_new_book(client):
"""Test adding a new book via the API successfully."""
# Using a valid ISBN-13 (978-0-306-40615-7)
book_data = {
"title": "API Test Book",
"author": "Tester",
"isbn": "9780306406157",
"year": 2024
}
response = client.post("/books", json=book_data)
assert response.status_code == 201
assert response.json()["title"] == "API Test Book"
list_response = client.get("/books")
assert len(list_response.json()) == 1
assert list_response.json()[0]["isbn"] == "9780306406157"
def test_add_book_with_na_isbn(client):
"""Test adding a book with N/A ISBN (for books without ISBN)."""
book_data = {
"title": "Book Without ISBN",
"author": "Anonymous",
"isbn": "N/A",
"year": 2000
}
response = client.post("/books", json=book_data)
assert response.status_code == 201
assert response.json()["isbn"] == "N/A"
def test_add_book_with_invalid_isbn_fails(client):
"""Test that adding a book with an invalid ISBN returns a 422 error."""
book_data = {
"title": "Invalid ISBN Book",
"author": "Tester",
"isbn": "12345", # Invalid ISBN
"year": 2024
}
response = client.post("/books", json=book_data)
assert response.status_code == 422
def test_add_duplicate_book_fails(client):
"""Test that adding a book with a duplicate ISBN results in a 400 error."""
# Using a valid ISBN-10 (0-306-40615-2)
book_data = {"title": "Duplicate", "author": "Copy", "isbn": "0306406152", "year": 2024}
response1 = client.post("/books", json=book_data)
assert response1.status_code == 201
response2 = client.post("/books", json=book_data)
assert response2.status_code == 400
assert "already exists" in response2.json()["detail"]
def test_get_single_book(client):
"""Test retrieving a single book by its ISBN after adding it."""
# Using a valid ISBN-13
book_data = {"title": "Findable Book", "author": "Seeker", "isbn": "9780134685991", "year": 2022}
client.post("/books", json=book_data)
response = client.get("/books/9780134685991")
assert response.status_code == 200
assert response.json()["title"] == "Findable Book"
def test_get_nonexistent_book(client):
"""Test that trying to retrieve a book that doesn't exist returns a 404 error."""
response = client.get("/books/0000000000")
assert response.status_code == 404
def test_update_existing_book(client):
"""Test updating an existing book."""
# Using a valid ISBN-10
book_data = {"title": "Old Title", "author": "Old Author", "isbn": "080442957X", "year": 2021}
client.post("/books", json=book_data)
updated_data = {"title": "New Title", "author": "New Author", "isbn": "080442957X", "year": 2021, "available": False}
response = client.put("/books/080442957X", json=updated_data)
assert response.status_code == 200
assert response.json()["title"] == "New Title"
assert response.json()["available"] is False
def test_remove_existing_book(client):
"""Test removing a book."""
# Using a valid ISBN-13
book_data = {"title": "To Be Deleted", "author": "Deleter", "isbn": "9780596007126", "year": 2020}
client.post("/books", json=book_data)
response = client.delete("/books/9780596007126")
assert response.status_code == 204
get_response = client.get("/books/9780596007126")
assert get_response.status_code == 404
def test_health_check(client):
"""Test the health check endpoint."""
response = client.get("/health")
assert response.status_code == 200
data = response.json()
assert data["status"] == "healthy"
assert "books_count" in data