-
Notifications
You must be signed in to change notification settings - Fork 1
Add initial tests using pytest #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
""" WalkthroughA suite of test files and utilities has been added to support testing of authentication and category-related API endpoints in a Flask application. This includes pytest fixtures for database setup, user registration and login, comprehensive test cases for authentication and category operations, and utility functions for handling JWT token scenarios. A dedicated requirements file for testing dependencies is also introduced. Changes
Sequence Diagram(s)sequenceDiagram
participant Tester
participant Pytest
participant FlaskApp
participant Database
Tester->>Pytest: Run authentication/category tests
Pytest->>FlaskApp: Setup test client (fixture)
Pytest->>Database: Create test schema (fixture)
Pytest->>FlaskApp: Register user via /auth/register
FlaskApp->>Database: Insert user
Pytest->>FlaskApp: Login user via /auth/login
FlaskApp->>Database: Verify credentials
FlaskApp-->>Pytest: Return access/refresh tokens
Pytest->>FlaskApp: Perform API operations (CRUD)
FlaskApp->>Database: Read/Write category data
FlaskApp-->>Pytest: Return API responses
Pytest->>Database: Drop schema (teardown)
Poem
Tip ⚡️ Faster reviews with caching
Enjoy the performance boost—your workflow just got faster. ✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Nitpick comments (6)
requirements-test.txt (1)
1-3
: Consider adding more testing dependenciesFor comprehensive testing, consider adding other common testing dependencies like:
- pytest-cov (for code coverage)
- pytest-mock (for mocking)
- pytest-flask (for Flask-specific testing utilities)
tests/conftest.py (1)
10-19
: Add a session fixture for database operationsConsider adding a separate session fixture to handle database operations, which would make database setup more reusable and keep tests cleaner.
@pytest.fixture def session(): with app.app_context(): db.create_all() yield db.session db.session.remove() db.drop_all() @pytest.fixture def client(session): app.config['TESTING'] = True with app.test_client() as client: yield clienttests/utils.py (3)
6-11
: Add docstring to explain error response verificationThis utility function looks good, but adding a docstring would improve clarity about what error codes and formats are expected.
def verify_token_error_response(response, expected_code, status_code=401): + """ + Verify that a response contains the expected error code and has the correct status code. + + Args: + response: Flask response object + expected_code: The expected error code in the JSON response + status_code: The expected HTTP status code (defaults to 401) + """ assert response.status_code == status_code data = response.get_json() assert 'error' in data assert data['code'] == expected_code
17-24
: Consider handling edge cases in token utility functionsThe token generation utilities look good, but consider handling potential exceptions when creating tokens.
def get_expired_token_headers(app_context): + """Generate headers with an expired JWT token for testing invalid token scenarios.""" with app_context: - token = create_access_token(identity=str(1), expires_delta=timedelta(seconds=-1)) + try: + token = create_access_token(identity=str(1), expires_delta=timedelta(seconds=-1)) + except Exception as e: + # Log the exception or handle it appropriately + raise RuntimeError(f"Failed to create expired token: {str(e)}") return get_auth_header(token) def get_invalid_token_headers(): + """Generate headers with an invalid JWT token format for testing.""" return get_auth_header('invalid.token.format')
1-25
: Add function for standard auth headers creationConsider adding a helper function that creates valid authentication headers for a given user ID, which would be useful across tests.
def get_valid_token_headers(app_context, user_id): """ Generate headers with a valid JWT token for the given user ID. Args: app_context: Flask app context user_id: The user ID to include in the token Returns: Dict containing Authorization header with valid JWT token """ with app_context: token = create_access_token(identity=str(user_id)) return get_auth_header(token)tests/test_category.py (1)
67-68
: Consider more specific error handling for duplicate categoriesThe test expects a 500 status code for duplicate categories, which suggests the server is handling this as an internal error rather than a specific business rule violation.
Consider implementing a more specific error code (like 409 Conflict) for duplicate categories:
-assert response.status_code == 500 +assert response.status_code == 409Also consider checking for a specific error message in the response.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
requirements-test.txt
(1 hunks)tests/__init__.py
(1 hunks)tests/conftest.py
(1 hunks)tests/test_auth.py
(1 hunks)tests/test_category.py
(1 hunks)tests/utils.py
(1 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
tests/test_category.py
177-177: Redefinition of unused test_update_category_missing_token
from line 143
(F811)
🔇 Additional comments (16)
tests/__init__.py (1)
1-1
: LGTM!This empty file correctly marks the
tests
directory as a Python package, enabling proper importing of the test modules and fixtures.requirements-test.txt (1)
1-2
:✅ Verification successful
Verify pytest version 8.3.5
The specified pytest version 8.3.5 looks unusually high. As of my knowledge cutoff in April 2024, the latest pytest version was in the 7.x range.
🌐 Web query:
What is the latest version of pytest available?
💡 Result:
The latest version of pytest available as of May 2025 is 8.3.5[1][4][5]. This version was released on March 2, 2025[1][5].
Citations:
- 1: https://pypi.org/project/pytest/
- 2: https://github.com/pytest-dev/pytest/releases
- 3: https://pytest.org
- 4: https://docs.pytest.org/en/stable/getting-started.html
- 5: https://docs.pytest.org/en/stable/changelog.html
- 6: https://pypi.org/project/pytest-cov/
- 7: https://docs.pytest.org/en/7.1.x/getting-started.html
- 8: https://docs.pytest.org/en/stable/announce/index.html
pytest==8.3.5 is the latest release
pytest version 8.3.5 matches the current latest release (March 2, 2025) on PyPI, so no changes are needed.
• requirements-test.txt (lines 1–2)
tests/conftest.py (1)
21-32
: LGTM! Well-structured authentication fixturesThese fixtures provide clean abstractions for user registration and login operations, which will make the tests more maintainable and readable.
tests/utils.py (1)
13-14
: LGTM!Simple and effective helper function for creating authorization headers.
tests/test_auth.py (7)
12-16
: LGTM! Good use of autouse fixtureThe setup fixture running automatically before each test ensures that the database starts with no users, providing good test isolation.
19-27
: LGTM! Helpful helper methodThis utility method effectively verifies user existence in the database and returns the user object when needed, which helps avoid code duplication across tests.
35-46
: LGTM! Thorough invalid request testingThis helper method tests multiple invalid request scenarios, including empty payloads, partial payloads, and non-JSON data. The coverage of these edge cases is excellent.
49-56
: LGTM! Comprehensive register testThe test properly validates successful registration by checking the status code, response content, user count, and password hashing.
109-120
: LGTM! Effective token refresh testThe test correctly verifies that the refresh token can be used to obtain a new access token.
122-137
: LGTM! Good token validation testsThe test effectively validates both access token rejection and malformed token rejection for the refresh endpoint.
144-147
: LGTM! Good expired token handlingThe test properly verifies that expired tokens are rejected with the appropriate error response.
tests/test_category.py (5)
18-25
: LGTM! Well-designed fixture for authenticated headersThis fixture effectively encapsulates the authentication flow needed for secured endpoints, making the tests cleaner.
28-34
: LGTM! Good use of compositional fixturesThis fixture builds on the
create_authenticated_headers
fixture, which is a good example of composing fixtures to create higher-level test utilities.
126-132
: LGTM! Good token expiration testThe test properly verifies that expired tokens are rejected and the database state remains unchanged.
96-112
: LGTM! Comprehensive category update testThe test properly checks both the response and the database state after updating a category, including verifying that the old name no longer exists.
114-125
: LGTM! Thorough category deletion testThe test correctly verifies that the category is deleted by checking both the API response and the database state.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
tests/test_auth.py (1)
85-95
: Fixed assertion for refresh token check.The test correctly verifies the successful login response, including checking that both access and refresh tokens are returned with non-zero length.
🧹 Nitpick comments (1)
tests/test_auth.py (1)
1-148
: Consider reducing excessive empty lines throughout the file.While the code structure is good, there are many instances of multiple consecutive empty lines that could be reduced to a single empty line for better readability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
tests/test_auth.py
(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
tests/test_auth.py (3)
app/models.py (2)
User
(11-49)get
(30-35)tests/conftest.py (3)
client
(11-18)register_user
(22-25)login_user
(29-32)tests/utils.py (4)
get_auth_header
(13-14)verify_token_error_response
(6-10)get_invalid_token_headers
(23-24)get_expired_token_headers
(17-20)
🔇 Additional comments (16)
tests/test_auth.py (16)
1-5
: Good job importing necessary modules for testing.The imports are appropriate and focused on what's needed for these tests.
7-10
: Good use of class constants for test data.Defining test credentials as class constants makes it easy to maintain and update these values across all test methods.
12-17
: Effective test setup with database verification.The autouse fixture ensures proper setup before each test and verifies the database starts empty. The app context usage is appropriate for database operations.
19-28
: Well-structured helper method for user verification.This helper method effectively checks user existence with appropriate assertions and supports both positive and negative verification through the
should_exist
parameter.
30-33
: Useful database helper method.This method provides a clean interface for checking the user count, which is used consistently throughout the tests.
35-47
: Comprehensive invalid request testing.This helper method thoroughly tests different invalid request scenarios including empty JSON, missing fields, and non-JSON data. The status code assertions are appropriate for each case.
49-57
: Good test coverage for successful registration.This test properly verifies the registration flow including status code, response content, user creation, and password hashing.
59-67
: Appropriate test for duplicate email handling.This test correctly verifies that the API properly rejects duplicate email registrations with the appropriate status code and error message.
69-78
: Complete test for invalid email format.The test properly verifies error handling for invalid email formats, including checking the specific error code and ensuring no user is created.
80-83
: Concise test for invalid registration data.This test leverages the helper method to check various invalid registration scenarios in a DRY way.
97-103
: Good invalid password test.This test correctly verifies that the login endpoint properly rejects invalid credentials with the appropriate status code and error message.
105-107
: Reusable test for invalid login data.Good use of the helper method to test invalid login scenarios in a concise way.
109-120
: Well-structured token refresh test.This test properly verifies the token refresh flow by first getting tokens through login and then using the refresh token to obtain a new access token.
122-137
: Comprehensive invalid token tests.This test effectively covers two important invalid token scenarios:
- Using access token instead of refresh token
- Using a malformed token
The utility function usage promotes code reuse for verification.
139-142
: Good test for missing authorization header.This test verifies the API properly handles missing authorization headers during token refresh.
144-148
: Proper expired token handling test.This test correctly verifies that the API rejects expired tokens with the appropriate error response.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
tests/test_auth.py (2)
97-108
: Consider enhancing the token refresh test.While the test correctly verifies that a new access token is returned with a 200 status code, consider enhancing it by:
- Verifying the new access token is different from the original
- Checking if the response does/doesn't include a new refresh token based on your API's expected behavior
def test_refresh_token(self, register_user, login_user): register_user(self.TEST_EMAIL, self.TEST_PASSWORD) login_resp = login_user(self.TEST_EMAIL, self.TEST_PASSWORD) tokens = login_resp.get_json() refresh_token = tokens["refresh_token"] + original_access_token = tokens["access_token"] headers = utils.get_auth_header(refresh_token) refresh_resp = self.client.post("/auth/refresh", headers=headers) assert refresh_resp.status_code == 200 data = refresh_resp.get_json() assert "access_token" in data + assert data["access_token"] != original_access_token + # Depending on your API design: + # assert "refresh_token" not in data # If refresh tokens aren't rotated
1-135
: Consider adding additional authentication edge cases.The test suite is comprehensive, but could be enhanced with additional edge cases:
- Login attempt with a non-existent user
- Registration with a weak password (if your API enforces password complexity)
- Testing CSRF protection (if implemented)
These would further strengthen your test coverage for security-related concerns.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
tests/conftest.py
(1 hunks)tests/test_auth.py
(1 hunks)tests/test_category.py
(1 hunks)tests/utils.py
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- tests/utils.py
🚧 Files skipped from review as they are similar to previous changes (2)
- tests/conftest.py
- tests/test_category.py
🔇 Additional comments (8)
tests/test_auth.py (8)
1-16
: Good test class setup and initialization approach.The class setup with a dedicated autouse fixture ensures each test starts with a clean database state. The application context is properly managed, and the initial assertion that the database is empty provides a solid foundation for the rest of the tests.
17-30
: Well-structured helper methods for database verification.Your helper methods for verifying users in the database and counting users are well-encapsulated and properly manage the application context. This promotes code reuse and keeps the actual test methods focused on their primary assertions.
31-43
: Comprehensive validation of invalid request data scenarios.The helper method
_test_invalid_request_data
covers multiple failure cases:
- Empty JSON payload
- Missing password field
- Missing email field
- Non-JSON content type
This approach ensures consistent validation across different endpoints without code duplication.
44-52
: Good test for successful registration with security validation.The test properly verifies:
- HTTP status code 201 for successful creation
- Response message
- User existence in the database
- Password hashing security (checking that passwords aren't stored in plaintext)
This is a comprehensive test with appropriate security checks.
53-75
: Complete coverage of registration error scenarios.These tests thoroughly verify registration failure cases:
- Duplicate email detection
- Invalid email format validation
- Invalid request data handling
Each test verifies both the appropriate HTTP status code and error message, along with database state validation.
85-85
: Fixed assertion now correctly checks refresh token length.The assertion properly verifies the length of the refresh token rather than a list containing a string.
109-124
: Thorough testing of invalid token scenarios.The test properly verifies token refresh fails with appropriate error responses when:
- Using an access token instead of a refresh token
- Using a malformed token
The reuse of the utility function
verify_token_error_response
maintains consistency in error response validation.
125-135
: Good coverage of token edge cases.These tests properly verify error handling for missing authorization headers and expired tokens. Using utility functions from
tests.utils
keeps the tests readable and focused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
tests/test_auth.py (2)
87-93
: Consider adding test for non-existent user login.The tests cover invalid password scenarios but not the case where a user tries to log in with an email that doesn't exist in the system.
+ def test_login_nonexistent_user(self, login_user): + response = login_user("nonexistent@example.com", self.TEST_PASSWORD) + + assert response.status_code == 401 + assert b"Invalid username or password" in response.data
132-138
: Consider validating token structure in tests.While testing token expiry is good, consider adding validation of token structure (JWT format) and claims to ensure tokens contain expected data (user ID, expiry time, etc.).
+ def test_token_structure(self, register_user, login_user): + register_user(self.TEST_EMAIL, self.TEST_PASSWORD) + response = login_user(self.TEST_EMAIL, self.TEST_PASSWORD) + data = response.get_json() + + # Verify token format (header.payload.signature) + access_token = data["access_token"] + refresh_token = data["refresh_token"] + assert len(access_token.split(".")) == 3 + assert len(refresh_token.split(".")) == 3 + + # Optional: If you have a way to decode and verify token contents + # decoded = utils.decode_token(access_token) + # assert decoded["sub"] == str(user_id) + # assert "exp" in decoded
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
tests/test_auth.py
(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
tests/test_auth.py (3)
app/models.py (2)
User
(11-49)get
(30-35)tests/conftest.py (3)
client
(12-19)register_user
(23-29)login_user
(33-37)tests/utils.py (4)
get_auth_header
(13-14)verify_token_error_response
(6-10)get_invalid_token_headers
(25-26)get_expired_token_headers
(17-22)
🔇 Additional comments (8)
tests/test_auth.py (8)
1-5
: Good organization with appropriate imports.The imports are correctly structured, importing pytest for testing and the necessary application modules.
11-16
: Well-structured setup fixture.The autouse fixture ensures clean test environment by setting up the test client and verifying the database is empty before each test. This provides proper isolation between test cases.
17-26
: Good database verification helper method.The
_verify_user_in_db
helper effectively validates user existence and attributes, properly handling the app context for database operations.
31-43
: Well-designed test helper for invalid request scenarios.This helper covers multiple invalid request scenarios efficiently, including missing fields and incorrect content types.
44-52
: Good test coverage for successful registration.The test correctly verifies:
- HTTP status code
- Response message
- User count in database
- User existence
- Password hashing (not storing plain text)
76-86
: Fixed token length assertion.The assertion for refresh token length is now correctly checking the actual token rather than a list reference.
97-111
: Good token refresh test.The test properly verifies that:
- A new access token is issued
- The new token is different from the original
- No new refresh token is issued
- The correct status code is returned
112-127
: Thorough testing of invalid refresh token scenarios.The test covers both using an access token incorrectly for refresh and using a malformed token.
Summary by CodeRabbit
Tests
Chores