Skip to content

Commit 4c85183

Browse files
committed
Add documentation for frontend testing methodologies
1 parent af5e774 commit 4c85183

File tree

1 file changed

+239
-0
lines changed

1 file changed

+239
-0
lines changed
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
# Frontend Testing Methodologies for Django Projects
2+
## Overview
3+
4+
This document outlines testing methodologies for Django projects with HTML forms and JavaScript enhancements, focusing on Python-based testing solutions. While going through the codebase, I can see it is primarily a JavaScript-heavy frontend that uses plain HTML forms enhanced with JavaScript/jQuery rather than server-rendered Django forms. Django forms are being used only in the admin panel of the project.
5+
6+
## Primary Testing Tools
7+
8+
### 1. Selenium with Python (Chosen)
9+
10+
#### Capabilities
11+
- Full browser automation
12+
- JavaScript execution support
13+
- Real DOM interaction
14+
- Cross-browser testing
15+
- Modal dialog handling
16+
- AJAX request testing
17+
- File upload testing
18+
- DataTables interaction
19+
20+
#### Implementation
21+
```python
22+
from selenium import webdriver
23+
from selenium.webdriver.common.by import By
24+
from selenium.webdriver.support.ui import WebDriverWait
25+
from selenium.webdriver.support import expected_conditions as EC
26+
27+
class TestCollectionDetail:
28+
def setup_method(self):
29+
self.driver = webdriver.Chrome()
30+
self.wait = WebDriverWait(self.driver, 10)
31+
32+
def test_title_change_modal(self):
33+
# Example test for title change modal
34+
self.driver.get("/collections/1/")
35+
title_button = self.wait.until(
36+
EC.element_to_be_clickable((By.ID, "change-title-btn"))
37+
)
38+
title_button.click()
39+
40+
modal = self.wait.until(
41+
EC.visibility_of_element_located((By.ID, "title-modal"))
42+
)
43+
44+
form = modal.find_element(By.TAG_NAME, "form")
45+
input_field = form.find_element(By.NAME, "title")
46+
input_field.send_keys("New Title")
47+
form.submit()
48+
49+
# Wait for AJAX completion
50+
self.wait.until(
51+
EC.text_to_be_present_in_element((By.ID, "collection-title"), "New Title")
52+
)
53+
```
54+
55+
#### Pros
56+
- Complete end-to-end testing
57+
- Real browser interaction
58+
- JavaScript support
59+
- Comprehensive API
60+
- Strong community support
61+
62+
#### Drawbacks
63+
- Slower execution
64+
- Browser dependencies
65+
- More complex setup
66+
- Can be flaky with timing issues
67+
68+
### 2. pytest-django with django-test-client
69+
70+
#### Capabilities
71+
- Form submission testing
72+
- Response validation
73+
- Header verification
74+
- Status code checking
75+
- Session handling
76+
- Template rendering testing
77+
78+
#### Implementation
79+
```python
80+
import pytest
81+
from django.urls import reverse
82+
83+
@pytest.mark.django_db
84+
class TestCollectionForms:
85+
def test_collection_create(self, client):
86+
url = reverse('collection_create')
87+
data = {
88+
'title': 'Test Collection',
89+
'division': 'division1',
90+
'workflow_status': 'active'
91+
}
92+
response = client.post(url, data)
93+
assert response.status_code == 302 # Redirect after success
94+
95+
# Verify creation
96+
response = client.get(reverse('collection_detail', kwargs={'pk': 1}))
97+
assert 'Test Collection' in response.content.decode()
98+
```
99+
100+
#### Pros
101+
- Fast execution
102+
- No browser dependency
103+
- Simpler setup
104+
- Integrated with Django
105+
106+
#### Drawbacks
107+
- **No JavaScript support (Dealbreaker)**
108+
- Limited DOM interaction
109+
- Can't test real user interactions
110+
111+
### 3. Playwright for Python
112+
113+
#### Capabilities
114+
- Modern browser automation
115+
- Async/await support
116+
- Network interception
117+
- Mobile device emulation
118+
- Automatic waiting
119+
- Screenshot and video capture
120+
121+
#### Implementation
122+
```python
123+
from playwright.sync_api import sync_playwright
124+
125+
def test_modal_form_submission():
126+
with sync_playwright() as p:
127+
browser = p.chromium.launch()
128+
page = browser.new_page()
129+
130+
page.goto("/collections/")
131+
132+
# Click button to open modal
133+
page.click("#add-collection-btn")
134+
135+
# Fill form in modal
136+
page.fill("#title-input", "New Collection")
137+
page.fill("#division-input", "Division A")
138+
139+
# Submit form
140+
page.click("#submit-btn")
141+
142+
# Wait for success message
143+
success_message = page.wait_for_selector(".toast-success")
144+
assert "Collection created" in success_message.text_content()
145+
146+
browser.close()
147+
```
148+
149+
#### Pros
150+
- Modern API design
151+
- Better stability than Selenium
152+
- Built-in async support
153+
- Powerful debugging tools
154+
155+
#### Drawbacks
156+
- **Newer tool, smaller community (Dealbreaker)**
157+
- Additional system dependencies
158+
- Learning curve for async features
159+
160+
161+
### 4. Beautiful Soup with Requests
162+
A combination for testing HTML structure and content.
163+
164+
**Capabilities:**
165+
- HTML parsing and validation
166+
- Content extraction
167+
- Structure verification
168+
- Link checking
169+
- Form field validation
170+
- Template testing
171+
172+
**Pros:**
173+
- Lightweight solution
174+
- Flexible HTML parsing
175+
- No browser dependency
176+
- Fast execution
177+
- Simple API
178+
- Low resource usage
179+
180+
**Drawbacks:**
181+
- **No JavaScript support (Dealbreaker)**
182+
- Limited interaction testing
183+
- No visual testing
184+
- Basic functionality only
185+
- No real browser simulation
186+
187+
## Testing Strategy Recommendations
188+
189+
1. **Primary Testing Tool**: Selenium with Python
190+
- Best suited for your JavaScript-heavy interface
191+
- Handles modals and AJAX naturally
192+
- Extensive documentation and community support
193+
194+
2. **Test Coverage Areas**:
195+
- Modal form interactions
196+
- AJAX submissions
197+
- DataTables functionality
198+
- Form validation
199+
- Success/error messages
200+
- URL routing
201+
- DOM updates
202+
203+
## Implementation Steps
204+
205+
1. Set up testing environment:
206+
```bash
207+
pip install selenium pytest pytest-django
208+
```
209+
210+
2. Create base test classes:
211+
```python
212+
import pytest
213+
from selenium import webdriver
214+
215+
class BaseUITest:
216+
@pytest.fixture(autouse=True)
217+
def setup_class(self):
218+
self.driver = webdriver.Chrome()
219+
yield
220+
self.driver.quit()
221+
222+
def login(self):
223+
# Common login logic
224+
pass
225+
```
226+
227+
3. Organize tests by feature:
228+
```python
229+
class TestCollectionManagement(BaseUITest):
230+
def test_create_collection(self):
231+
pass
232+
233+
def test_edit_collection(self):
234+
pass
235+
236+
class TestURLPatterns(BaseUITest):
237+
def test_add_include_pattern(self):
238+
pass
239+
```

0 commit comments

Comments
 (0)