UNC BACS 350

Web Apps with Python/Django

Logo

Page Probe Test Design Pattern

Demo Code

Data

probe/models.py

```python from django.db import models from django.urls.base import reverse_lazy

class Probe(models.Model):

name = models.CharField(max_length=100)
page = models.URLField()
text = models.CharField(max_length=100)

def __str__(self):
    return f'{self.name} - {self.page}'

def get_absolute_url(self):
    return reverse_lazy('probe_list')

@staticmethod
def create(**kwargs):
    c = Probe.objects.get_or_create(name=kwargs.get('name'))[0]
    c.page = kwargs.get('page')
    c.text = kwargs.get('text')
    c.save()
    return c

class Result(models.Model):

probe = models.ForeignKey(Probe, on_delete=models.CASCADE, editable=False)
date = models.DateTimeField(auto_now=True)
output = models.TextField(default='Not yet run')
passed = models.BooleanField(default=False)

def __str__(self):
    return f'{self.probe.name} - {self.date} - {self.passed}'

def get_absolute_url(self):
    return reverse_lazy('probe_list')

@staticmethod
def create(**kwargs):
    c = Result.objects.create(probe=kwargs.get('probe'))
    c.output = kwargs.get('output')
    c.passed = kwargs.get('passed')
    c.save()
    return c

```

Execute Page Probe Tests

probe/probe.py

```python def launch_all_probes(): for probe in Probe.objects.all(): execute_probe(probe)

def execute_probe(probe): try: response = get(probe.page) except: response = None if not response: status = f'Status Code: Domain not found, {probe.page}' passed = False elif response.status_code != 200: status = f'Status Code: {response.status_code}' passed = False elif probe.text not in response.text: status = f'Text not found: {probe.text}' passed = False else: status = f'Matched: {probe.text}' passed = True Result.create(probe=probe, output=status, passed=passed) ```

Views

probe/probe_views.py

```python from django.shortcuts import render from django.urls import reverse_lazy, reverse from django.views.generic import (CreateView, DeleteView, DetailView, ListView, RedirectView, UpdateView) from requests import get

from .models import Probe from .probe import clear_probe_history, execute_probe, launch_all_probes, result_list

class ProbeView(RedirectView): url = reverse_lazy('probe_list')

class ProbeListView(ListView): template_name = 'probe_list.html' model = Probe

class ProbeDetailView(DetailView): template_name = 'probe_detail.html' model = Probe

def get_context_data(self, **kwargs):
    kwargs = super().get_context_data(**kwargs)
    probe = kwargs['object']
    execute_probe(probe)
    kwargs['results'] = result_list(probe)
    return kwargs

class ProbeLaunchView(RedirectView):

def get_redirect_url(self, *args, **kwargs):
    launch_all_probes()
    return reverse('probe_list')

class ProbeClearView(RedirectView):

def get_redirect_url(self, *args, **kwargs):
    probe_pk = self.kwargs.get('pk')
    clear_probe_history(probe_pk)
    return reverse('probe_detail', args=[probe_pk])

class ProbeCreateView(CreateView): template_name = "probe_add.html" model = Probe fields = 'all'

def form_valid(self, form):
    form.instance.author_id = 1
    return super().form_valid(form)

class ProbeUpdateView(UpdateView): template_name = "probe_edit.html" model = Probe fields = 'all'

class ProbeDeleteView(DeleteView): model = Probe template_name = 'probe_delete.html' success_url = reverse_lazy('probe_list')

```

Templates

templates/probe_detail.html

```html
{% extends 'theme.html' %}

{% block content %}

Probe Details

Name {{ object.name }}
Page URL {{ object.page }}
Text to Match {{ object.text }}

Test Results

{% for r in results %} {% endfor %}
Date Pass/Fail Text Output
{{ r.date }} {% if r.passed %}PASS{% else %}FAIL{% endif %} {{ r.output }}
Probe List Clear History Edit Probe Delete Probe

{% endblock content %} ```

URL Routes

config/urls.py

```python from django.urls import path from django.urls.conf import include

from probe.views_probe import ProbeView

urlpatterns = [

path('', ProbeView.as_view()),
path('probe/', include('probe.urls_probe')),

] ```

probe/probe_urls.py

```python from django.urls import path from .views_probe import (ProbeClearView, ProbeCreateView, ProbeDeleteView, ProbeDetailView, ProbeLaunchView, ProbeListView, ProbeUpdateView) urlpatterns = [

path('',                       ProbeListView.as_view(),    name='probe_list'),
path('<int:pk>',               ProbeDetailView.as_view(),  name='probe_detail'),
path('add',                    ProbeCreateView.as_view(),  name='probe_add'),
path('<int:pk>/',              ProbeUpdateView.as_view(),  name='probe_edit'),
path('<int:pk>/delete',        ProbeDeleteView.as_view(),  name='probe_delete'),
path('<int:pk>/clear',         ProbeClearView.as_view(),   name='probe_clear'),
path('test',                   ProbeLaunchView.as_view(),  name='probe_launch'),

] ```