Added tests for the views of Collections, Extraction, Subscription, Notes and Search. Fixed some bugs #131
Added tests for the views of Collections, Extraction, Subscription, Notes and Search. Fixed some bugs #131
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR adds default ordering to Collection and Report models to resolve Django's UnorderedObjectListWarning during pagination, and introduces comprehensive smoke tests for collection views.
- Added
ordering = ["-created", "name"]to Collection model's Meta class and updated CollectionManager - Added
ordering = ["-created_at", "document_id"]to Report model's Meta class - Created 16 smoke tests covering collection views including CRUD operations, authorization checks, and edge cases
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| radis/collections/models.py | Added default ordering to Collection model and updated manager's get_queryset method |
| radis/reports/models.py | Added default ordering to Report model |
| radis/collections/tests/test_views.py | New test file with comprehensive view tests for collections |
| radis/collections/tests/init.py | New test package initialization file |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| class CollectionManager(models.Manager["Collection"]): | ||
| def get_queryset(self) -> CollectionQuerySet: | ||
| return CollectionQuerySet(self.model) | ||
| return CollectionQuerySet(self.model).order_by("-created", "name") |
There was a problem hiding this comment.
The ordering is duplicated between the manager's get_queryset method and the Meta class. Remove the .order_by() call from the manager since the Meta ordering will already apply this default ordering to all querysets.
| return CollectionQuerySet(self.model).order_by("-created", "name") | |
| return CollectionQuerySet(self.model) |
|
…ubscription/models and views
Pull Request Review - #131OverviewThis PR adds comprehensive view tests for Collections, Extractions, and Subscriptions modules, plus important bug fixes in core models and views. Overall, this is a solid contribution that improves test coverage significantly. ✅ StrengthsTest Coverage
Bug Fixes
🔍 Issues & Recommendations1. Critical: Redundant ordering in CollectionManagerLocation: radis/collections/models.py:28 def get_queryset(self) -> CollectionQuerySet:
return CollectionQuerySet(self.model).order_by("-created", "name")Issue: This ordering is now redundant since you added Recommendation: Remove the def get_queryset(self) -> CollectionQuerySet:
return CollectionQuerySet(self.model)2. Bug: Duplicate ordering in SubscriptionListViewLocation: radis/subscriptions/views.py:43 According to the diff, the view adds Recommendation: Remove the explicit 3. Logic concern: Empty job handlingLocation: radis/core/models.py:86-90 if not self.tasks.exists():
self.status = AnalysisJob.Status.CANCELED
self.message = "No tasks remaining."
self.save()
return FalseIssue: Setting status to CANCELED when there are no tasks might not be semantically correct for all cases. What if a job legitimately has no tasks yet because it's still being prepared? This could cause issues with job lifecycle management. Questions:
Recommendation: Add a check to ensure this only applies when tasks existed previously, or document this behavior clearly. 4. Test quality issuesa) Weak assertions in some testsExample from radis/collections/tests/test_views.py:37: def test_collection_create_view_post(client: Client):
# ...
response = client.post("/collections/create/", {"name": "Test Collection"})
assert response.status_code == 204Issue: Only checks status code, doesn't verify the collection was actually created. Recommendation: Add verification: assert response.status_code == 204
assert Collection.objects.filter(owner=user, name="Test Collection").exists()b) Missing negative test cases
c) Hard-coded URLsAll tests use hard-coded URLs like Recommendation: Use from django.urls import reverse
def test_collection_list_view(client: Client):
# ...
response = client.get(reverse("collection_list")) # assuming URL name
assert response.status_code == 2005. Code style: Inconsistent factory usageLocation: radis/subscriptions/tests/test_views.py Some tests create test data inline while others use the Recommendation: Use factory methods consistently or use the factories directly. 6. Missing test scenariosCollections tests missing:
Extractions tests missing:
Subscriptions tests missing:
🔒 Security✅ Good: Proper authorization checks - users can only access their own resources ⚡ Performance✅ Good: Added model-level ordering prevents database from choosing random order 🧪 Test ExecutionRecommendation: Ensure all tests pass: pytest radis/collections/tests/test_views.py -v
pytest radis/extractions/tests/test_views.py -v
pytest radis/subscriptions/tests/test_views.py -v📋 SummaryMust Fix:
Should Fix: Nice to Have: Overall AssessmentThis PR adds significant value with comprehensive test coverage and important bug fixes. The code quality is generally good and follows Django best practices. The main issues are around redundant ordering logic and opportunities to make tests more robust. With the suggested fixes, this would be an excellent addition to the codebase. Recommendation: Request changes for the redundant ordering issues, then approve. Review generated with attention to Google Python Style Guide and Django best practices |
Pull Request Review - #131 (Updated Review)OverviewThis PR adds comprehensive view tests for Collections, Extractions, Subscriptions, and Search modules, plus important bug fixes in core models and views. The PR adds 1,271 additions across 15 files with excellent test coverage (17 tests for collections, 27 for extractions, and more for subscriptions/search). ✅ Strengths1. Excellent Test Coverage
2. Critical Bug Fixes✅ Core views fix ( # Before (WRONG - AnalysisTask doesn't have owner field)
return self.model.objects.filter(owner=self.request.user)
# After (CORRECT - follows the foreign key relationship)
return self.model.objects.filter(job__owner=self.request.user)This fixes a critical bug where task deletion/reset would fail. Excellent catch! ✅ Empty job handling ( 3. Pagination ImprovementsAdded
4. Good Testing Patterns
5. Factory Improvements✅ CollectionFactory fix ( # Before
name = factory.Faker("sentence") # Could exceed 64 char limit
# After
name = factory.LazyAttribute(lambda obj: fake.sentence(nb_words=3)[:60]) # Respects model constraint🔍 Issues & Recommendations🔴 Critical Issues1. Redundant ordering in CollectionManagerLocation: Issue: The manager's def get_queryset(self) -> CollectionQuerySet:
return CollectionQuerySet(self.model).order_by("-created", "name") # REDUNDANTWhy it's a problem:
Fix: def get_queryset(self) -> CollectionQuerySet:
return CollectionQuerySet(self.model) # Meta.ordering will be applied automatically2. Potential issue with empty job logicLocation: Current code: if not self.tasks.exists():
self.status = AnalysisJob.Status.CANCELED
self.message = "No tasks remaining."
self.save()
return FalseConcern: This marks a job as CANCELED whenever it has zero tasks, but this might not be correct for jobs that legitimately have no tasks yet (e.g., during initial preparation). Questions:
Recommendation: Add a state check or document this behavior clearly. Consider: # Only cancel if we previously had tasks
if not self.tasks.exists() and self.status not in [self.Status.UNVERIFIED, self.Status.PREPARING]:
self.status = AnalysisJob.Status.CANCELED
# ...🟡 Important Issues3. Hard-coded URLs in testsAll test files use hard-coded URLs: response = client.get("/collections/")
response = client.post(f"/collections/{collection.pk}/delete/")Why it's a problem:
Fix: Use from django.urls import reverse
response = client.get(reverse("collection_list"))
response = client.post(reverse("collection_delete", args=[collection.pk]))4. Weak test assertionsMany tests only check status codes without verifying actual data changes. Example ( def test_collection_create_view_post(client: Client):
user = UserFactory.create(is_active=True)
client.force_login(user)
response = client.post("/collections/create/", {"name": "Test Collection"})
assert response.status_code == 204 # Only checks status codeImprovement: def test_collection_create_view_post(client: Client):
user = UserFactory.create(is_active=True)
client.force_login(user)
response = client.post("/collections/create/", {"name": "Test Collection"})
assert response.status_code == 204
# Verify the collection was actually created
assert Collection.objects.filter(owner=user, name="Test Collection").exists()
collection = Collection.objects.get(owner=user, name="Test Collection")
assert collection.reports.count() == 0Similar issue in:
5. Missing negative test casesThe tests focus on happy paths but miss important error cases: Missing tests: # Collections
def test_collection_create_with_empty_name() # Should fail validation
def test_collection_create_with_too_long_name() # 64 char limit
def test_collection_create_duplicate_name() # UniqueConstraint test
# Extractions
def test_extraction_job_state_transitions() # Verify UNVERIFIED -> PENDING -> IN_PROGRESS -> SUCCESS
def test_extraction_task_delete_updates_job_status() # Verify update_job_state() is called
# General
def test_with_invalid_pk() # Access non-existent resource
def test_with_special_characters_in_names()6. Inconsistent factory usageLocation: Some tests use helper functions, others create factories inline, creating inconsistency: # Some tests use this
subscription = create_test_subscription(owner=user)
# Others do this
subscription = SubscriptionFactory.create(owner=user)Recommendation: Choose one approach and use it consistently. 🟢 Minor Issues7. Missing type hints in test helpersHelper functions lack return type annotations: # Current
def create_test_report():
language = LanguageFactory.create(code="en")
return ReportFactory.create(language=language)
# Better
def create_test_report() -> Report:
language = LanguageFactory.create(code="en")
return ReportFactory.create(language=language)8. Incomplete test scenariosWhile coverage is good, some scenarios are missing: Collections:
Extractions:
Subscriptions:
9. Comment in SubscriptionCreateViewLocation: class SubscriptionCreateView(LoginRequiredMixin, CreateView): # TODO: Add PermissionRequiredMixinThis TODO wasn't addressed. Is permission checking needed for creating subscriptions? 🔒 Security Assessment✅ Good:
⚡ Performance Considerations✅ Good:
# In SubscriptionDetailView
def get_queryset(self):
return super().get_queryset().filter(owner=self.request.user).prefetch_related("questions")
🧪 Test Execution RecommendationsRun the new tests to ensure they all pass: # Run all new tests
pytest radis/collections/tests/test_views.py -v
pytest radis/extractions/tests/test_views.py -v
pytest radis/subscriptions/tests/test_views.py -v
pytest radis/search/tests/test_views.py -v
# Check coverage
pytest --cov=radis/collections --cov=radis/extractions --cov=radis/subscriptions radis/📋 SummaryMust Fix Before Merge:
Should Fix:
Nice to Have:
Overall AssessmentScore: 8/10 ⭐ This is a strong PR that adds significant value:
The main issues are:
Recommendation: Request changes for the critical issues (redundant ordering, empty job logic clarification, hard-coded URLs), then approve. The test improvements (stronger assertions, negative cases) can be addressed in follow-up PRs if time is a factor. Code Quality Checklist
Great work on this PR! The test coverage is excellent and the bug fixes are important. Looking forward to seeing this merged once the critical issues are addressed. 🚀 |
Pull Request Review: Test Views and Bug FixesSummaryThis PR adds comprehensive test coverage for views across multiple modules (collections, extraction, subscription, search, notes) and fixes several important bugs. Overall, this is a solid contribution that significantly improves test coverage and addresses real issues. ✅ StrengthsExcellent Test Coverage
Important Bug Fixes
Code Quality
🔍 Issues & Recommendations1. Model Ordering Changes (Medium Priority)Files: Issue: Ordering is defined in TWO places - both in the model # radis/collections/models.py:27 - ordering in manager
def get_queryset(self) -> CollectionQuerySet:
return CollectionQuerySet(self.model).order_by("-created", "name")
# radis/collections/models.py:57 - ordering in Meta
class Meta:
ordering = ["-created", "name"]Recommendation: Remove the duplicate 2. Test Hardcoded URLs vs Reverse Lookups (Low-Medium Priority)Issue: Most tests use hardcoded URLs ( Examples: # collections/tests/test_views.py:20
response = client.get("/collections/") # Hardcoded
# notes/tests/test_views.py:21
response = client.get(reverse("note_list")) # Using reverseRecommendation: Consistently use 3. Missing Test Data Validation (Low Priority)Issue: Most tests only verify status codes without checking response content or database state. Example: # radis/collections/tests/test_views.py:34-39
def test_collection_create_view_post(client: Client):
user = UserFactory.create(is_active=True)
client.force_login(user)
response = client.post("/collections/create/", {"name": "Test Collection"})
assert response.status_code == 204
# Missing: Verify collection was actually created in databaseRecommendation: Add assertions to verify database state changes: assert response.status_code == 204
assert Collection.objects.filter(owner=user, name="Test Collection").exists()4. Empty Task Logic Concern (Medium Priority)File: Issue: When there are no tasks, the job is set to Question: Should a job with zero tasks be Recommendation: Verify this status is correct for your use cases, particularly:
5. Factory Name Truncation (Low Priority)File: name = factory.LazyAttribute(lambda obj: fake.sentence(nb_words=3)[:60])Issue: Truncating at position 60 could cut mid-word, creating awkward test data like "This is a sent". Recommendation: Either:
6. Test Helper Function Inconsistency (Very Low Priority)Issue: Helper functions like Recommendation: Consider a consistent pattern for test helpers across all modules for better maintainability. 🔒 Security AssessmentStatus: ✅ No security concerns identified
⚡ Performance ConsiderationsStatus: ✅ Minimal performance impact
📊 Test CoverageStatus: ✅ Excellent This PR adds 1,547 lines of test code covering:
All major view operations are tested including CRUD operations, authorization, and edge cases. 📝 Overall RecommendationStatus: ✅ Approve with minor suggestions This PR significantly improves the codebase by:
Before Merging:
Suggested Follow-up Work:
Great work on improving test coverage! 🎉 |
Pull Request Review: View Tests and Bug FixesThanks for this comprehensive PR adding test coverage for multiple modules! Overall, this is a solid contribution that significantly improves the test suite. Below are my detailed findings and recommendations. ✅ Strengths
🐛 Bug Fixes AnalysisGood Fixes:
|
Added
test_viewsfor thecollection.ordering = ["-created", "name"]to the Meta class of the Collection model.ordering = ["-created_at", "document_id"]to the Meta class of the Report model.CollectionFactoryso that it matches the 64 character maximum length limit of the modelsAdded:
test_viewsfor the extraction module.core/viewsto filter byjob_ownerinstead ofowner, sinceAnalysisTaskdoesn’t have anownerfield but is linked via a foreign key toAnalysisJob, which has a owner field. (Fixed in a same way that we did in 'Adit'.orderingin theMetaclass ofmodels.py(extraction) to resolve pagination warnings.Added:
test_viewsfor the subscription module.factoriesforsubscriptionAdded
test_viewsfor thesearch.factoriesforsearchAdded
test_viewsfor thenotes.factoriesfornotesnotes/ views.py