Skip to content

Instantly share code, notes, and snippets.

@aitoehigie
Created May 25, 2024 10:08
Show Gist options
  • Save aitoehigie/5bff431082b67f52e993465334422e6d to your computer and use it in GitHub Desktop.
Save aitoehigie/5bff431082b67f52e993465334422e6d to your computer and use it in GitHub Desktop.
# myapp/management/commands/make_smoke_tests.py
from django.core.management.base import BaseCommand
from django.urls import get_resolver, URLPattern, URLResolver
import re
import os
class Command(BaseCommand):
help = 'Generates smoke tests for projects.'
def add_arguments(self, parser):
parser.add_argument('output_file', nargs='?', default='smoke_tests.py', help='Path to the output file for the generated tests')
def handle(self, *args, **options):
urlconf = get_resolver(None)
output_file = options['output_file']
self.generate_smoke_tests(urlconf, output_file)
def generate_smoke_tests(self, urlconf, output_file, prefix=''):
with open(output_file, 'w') as f:
f.write("# Generated smoke tests\n")
f.write("from django.test import Client\n")
f.write("import pytest\n\n\n")
f.write("@pytest.mark.django_db\n")
f.write("class TestSmoke:\n")
f.write(" client = Client()\n\n")
self._write_smoke_tests(urlconf, f, prefix)
def _write_smoke_tests(self, urlconf, file, prefix):
for pattern in urlconf.url_patterns:
if isinstance(pattern, URLResolver):
self._write_smoke_tests(pattern, file, prefix + pattern.pattern.regex.pattern)
elif isinstance(pattern, URLPattern):
if pattern.name:
url = f"/{prefix}{pattern.pattern.regex.pattern}".replace('^', '').replace('$', '').rstrip('/')
params = self._extract_url_params(url)
url_with_params = self._build_url_with_params(url, params)
self._write_test(file, pattern.name, url_with_params, 'get')
self._write_test(file, pattern.name, url_with_params, 'post')
self._write_test(file, pattern.name, url_with_params, 'put')
self._write_test(file, pattern.name, url_with_params, 'delete')
def _extract_url_params(self, url):
return re.findall(r'<(\w+:\w+)>', url)
def _build_url_with_params(self, url, params):
for param in params:
param_type, param_name = param.split(':')
if param_type == 'int':
url = url.replace(f'<{param}>', '1')
elif param_type == 'slug':
url = url.replace(f'<{param}>', 'test-slug')
else:
url = url.replace(f'<{param}>', 'test')
return url
def _write_test(self, file, name, url, method):
test_name = f"test_{method}_{name}"
file.write(f" def {test_name}(self):\n")
file.write(f" response = self.client.{method}('{url}/')\n")
file.write(f" assert response.status_code == 200\n\n")
@abe-101
Copy link

abe-101 commented May 28, 2024

Thank for the improvements

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment