The problem
A Flask API with 120+ endpoints had zero tests. Every deployment broke 5-10 random features. The team spent 70% of their time fixing regressions. Authentication would randomly fail, data validation let through garbage, and error responses crashed mobile apps. One developer's "quick fix" broke payment processing for 6 hours, costing $45,000 in lost sales.
How AI created this issue
The entire Flask app was built by copying ChatGPT examples, which never included tests. When asked for tests, ChatGPT generated useless placeholders:
# ChatGPT's "test" examples
def test_user_endpoint():
"""Test the user endpoint"""
assert True # TODO: Add actual test
def test_login():
"""Test login functionality"""
# This test will be implemented later
pass
def test_api():
"""Test API routes"""
print("Tests passed!") # Not actual tests
# ChatGPT's Flask route (no test provided)
@app.route('/api/users/', methods=['GET', 'PUT', 'DELETE'])
def user_operations(user_id):
if request.method == 'GET':
user = User.query.get(user_id)
return jsonify(user.to_dict())
elif request.method == 'PUT':
# No validation, no error handling
User.query.filter_by(id=user_id).update(request.json)
db.session.commit()
return jsonify({"status": "updated"})
elif request.method == 'DELETE':
User.query.filter_by(id=user_id).delete()
db.session.commit()
return jsonify({"status": "deleted"})
ChatGPT never demonstrated proper Flask testing patterns, fixtures, or test database setup. Developers skipped tests entirely, assuming they could "add them later." The AI's examples showed functionality but ignored quality assurance.
The solution
- Test infrastructure setup: Created proper test configuration and fixtures:
# conftest.py - Proper test setup import pytest from app import create_app, db from app.models import User, Role @pytest.fixture(scope='session') def app(): """Create application for testing""" app = create_app('testing') with app.app_context(): db.create_all() yield app db.drop_all() @pytest.fixture(scope='function') def client(app): """Test client for making requests""" return app.test_client() @pytest.fixture(scope='function') def auth_headers(client): """Get auth headers for protected routes""" # Create test user user = User(email='test@example.com') user.set_password('testpass123') db.session.add(user) db.session.commit() # Login and get token response = client.post('/api/auth/login', json={ 'email': 'test@example.com', 'password': 'testpass123' }) token = response.json['access_token'] return {'Authorization': f'Bearer {token}'}
- Comprehensive route testing: Tested all HTTP methods and edge cases:
# test_user_routes.py - Proper tests class TestUserRoutes: def test_get_user_success(self, client, auth_headers): """Test successful user retrieval""" # Create test user user = User(email='john@example.com', name='John Doe') db.session.add(user) db.session.commit() response = client.get( f'/api/users/{user.id}', headers=auth_headers ) assert response.status_code == 200 assert response.json['email'] == 'john@example.com' assert response.json['name'] == 'John Doe' def test_get_nonexistent_user(self, client, auth_headers): """Test 404 for missing user""" response = client.get( '/api/users/99999', headers=auth_headers ) assert response.status_code == 404 assert 'User not found' in response.json['error'] def test_update_user_validation(self, client, auth_headers): """Test input validation on update""" user = User(email='test@example.com') db.session.add(user) db.session.commit() # Invalid email format response = client.put( f'/api/users/{user.id}', headers=auth_headers, json={'email': 'not-an-email'} ) assert response.status_code == 400 assert 'Invalid email format' in response.json['error'] def test_delete_user_cascade(self, client, auth_headers): """Test cascading deletes work properly""" # Create user with related data user = User(email='delete@example.com') # ... setup related data response = client.delete( f'/api/users/{user.id}', headers=auth_headers ) assert response.status_code == 204 assert User.query.get(user.id) is None # Assert related data also deleted
- Integration testing: Tested complete user flows
- Performance tests: Added load testing to catch N+1 queries
- CI/CD integration: Tests run automatically on every commit
The results
- Test coverage: 0% → 94% across all routes
- Production bugs: 5-10 per release → 0.3 per release
- Development velocity increased 2.8x with confidence to refactor
- Deployment frequency: Weekly → Multiple times daily
- Customer complaints dropped 91%
- Saved $180,000/year in emergency fixes and lost sales
The team learned that AI-generated code without tests is technical debt. They now require 80% test coverage for all new code and use TDD for critical features. Tests aren't optional - they're the safety net that makes continuous deployment possible.
Ready to fix your codebase?
Let us analyze your application and resolve these issues before they impact your users.
Get Diagnostic Assessment →