mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2024-11-27 03:54:02 +03:00
Merge pull request #295 from crdoconnor/master
Added support for the Hitch integration testing framework.
This commit is contained in:
commit
0d68abcc39
16
{{cookiecutter.repo_name}}/.travis.yml
Normal file
16
{{cookiecutter.repo_name}}/.travis.yml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
before_install:
|
||||||
|
- sudo apt-get update -qq
|
||||||
|
- sudo apt-get install -qq build-essential gettext python-dev zlib1g-dev libpq-dev xvfb
|
||||||
|
- sudo apt-get install -qq libtiff4-dev libjpeg8-dev libfreetype6-dev liblcms1-dev libwebp-dev
|
||||||
|
- sudo apt-get install -qq graphviz-dev python-setuptools python3-dev python-virtualenv python-pip
|
||||||
|
- sudo apt-get install -qq firefox automake libtool libreadline6 libreadline6-dev libreadline-dev
|
||||||
|
- sudo apt-get install -qq libsqlite3-dev libxml2 libxml2-dev libssl-dev libbz2-dev wget curl llvm
|
||||||
|
language: python
|
||||||
|
python:
|
||||||
|
- "3.4"
|
||||||
|
install:
|
||||||
|
- "pip install hitch"
|
||||||
|
- "cd tests"
|
||||||
|
- "hitch init"
|
||||||
|
script:
|
||||||
|
- "hitch test . --extra '{\"xvfb\":true, \"pause_on_failure\":false}'"
|
|
@ -173,8 +173,32 @@ You must set the DSN url in production.
|
||||||
It's time to write the code!!!
|
It's time to write the code!!!
|
||||||
|
|
||||||
|
|
||||||
|
Running end to end integration tests
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
N.B. The integration tests will not run on Windows.
|
||||||
|
|
||||||
|
To install the test runner::
|
||||||
|
|
||||||
|
$ pip install hitch
|
||||||
|
|
||||||
|
To run the tests, enter the {{cookiecutter.repo_name}}/tests directory and run the following commands::
|
||||||
|
|
||||||
|
$ hitch init
|
||||||
|
|
||||||
|
Then run the stub test::
|
||||||
|
|
||||||
|
$ hitch test stub.test
|
||||||
|
|
||||||
|
This will download and compile python, postgres and redis and install all python requirements so the first time it runs it may take a while.
|
||||||
|
|
||||||
|
Subsequent test runs will be much quicker.
|
||||||
|
|
||||||
|
The testing framework runs Django, Celery (if enabled), Postgres, HitchSMTP (a mock SMTP server), Firefox/Selenium and Redis.
|
||||||
|
|
||||||
|
|
||||||
Deployment
|
Deployment
|
||||||
------------
|
----------
|
||||||
|
|
||||||
It is possible to deploy to Heroku or to your own server by using Dokku, an open source Heroku clone.
|
It is possible to deploy to Heroku or to your own server by using Dokku, an open source Heroku clone.
|
||||||
|
|
||||||
|
|
|
@ -22,3 +22,23 @@ libwebp-dev
|
||||||
|
|
||||||
##django-extensions
|
##django-extensions
|
||||||
graphviz-dev
|
graphviz-dev
|
||||||
|
|
||||||
|
##hitch
|
||||||
|
python-setuptools
|
||||||
|
python3-dev
|
||||||
|
python-virtualenv
|
||||||
|
python-pip
|
||||||
|
firefox
|
||||||
|
automake
|
||||||
|
libtool
|
||||||
|
libreadline6
|
||||||
|
libreadline6-dev
|
||||||
|
libreadline-dev
|
||||||
|
libsqlite3-dev
|
||||||
|
libxml2
|
||||||
|
libxml2-dev
|
||||||
|
libssl-dev
|
||||||
|
libbz2-dev
|
||||||
|
wget
|
||||||
|
curl
|
||||||
|
llvm
|
||||||
|
|
4
{{cookiecutter.repo_name}}/tests/base.yml
Normal file
4
{{cookiecutter.repo_name}}/tests/base.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{% raw %}{% for python_version in python_versions %}
|
||||||
|
{% block test scoped %}
|
||||||
|
{% endblock %}
|
||||||
|
{% endfor %}{% endraw %}
|
158
{{cookiecutter.repo_name}}/tests/engine.py
Normal file
158
{{cookiecutter.repo_name}}/tests/engine.py
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
from subprocess import call
|
||||||
|
from os import path
|
||||||
|
import hitchpostgres
|
||||||
|
import hitchselenium
|
||||||
|
import hitchpython
|
||||||
|
import hitchserve
|
||||||
|
import hitchredis
|
||||||
|
import hitchtest
|
||||||
|
import hitchsmtp
|
||||||
|
|
||||||
|
|
||||||
|
# Get directory above this file
|
||||||
|
PROJECT_DIRECTORY = path.abspath(path.join(path.dirname(__file__), '..'))
|
||||||
|
|
||||||
|
|
||||||
|
class ExecutionEngine(hitchtest.ExecutionEngine):
|
||||||
|
"""Engine for orchestating and interacting with the app."""
|
||||||
|
|
||||||
|
def set_up(self):
|
||||||
|
"""Ensure virtualenv present, then run all services."""
|
||||||
|
python_package = hitchpython.PythonPackage(
|
||||||
|
python_version=self.preconditions['python_version']
|
||||||
|
)
|
||||||
|
python_package.build()
|
||||||
|
python_package.verify()
|
||||||
|
|
||||||
|
call([
|
||||||
|
python_package.pip, "install", "-r",
|
||||||
|
path.join(PROJECT_DIRECTORY, "requirements/local.txt")
|
||||||
|
])
|
||||||
|
|
||||||
|
postgres_package = hitchpostgres.PostgresPackage(
|
||||||
|
version=self.settings["postgres_version"],
|
||||||
|
)
|
||||||
|
postgres_package.build()
|
||||||
|
postgres_package.verify()
|
||||||
|
|
||||||
|
redis_package = hitchredis.RedisPackage(version="2.8.4")
|
||||||
|
redis_package.build()
|
||||||
|
redis_package.verify()
|
||||||
|
|
||||||
|
self.services = hitchserve.ServiceBundle(
|
||||||
|
project_directory=PROJECT_DIRECTORY,
|
||||||
|
startup_timeout=float(self.settings["startup_timeout"]),
|
||||||
|
shutdown_timeout=5.0,
|
||||||
|
)
|
||||||
|
|
||||||
|
postgres_user = hitchpostgres.PostgresUser("{{cookiecutter.repo_name}}", "password")
|
||||||
|
|
||||||
|
self.services['Postgres'] = hitchpostgres.PostgresService(
|
||||||
|
postgres_package=postgres_package,
|
||||||
|
users=[postgres_user, ],
|
||||||
|
databases=[hitchpostgres.PostgresDatabase("{{cookiecutter.repo_name}}", postgres_user), ]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.services['HitchSMTP'] = hitchsmtp.HitchSMTPService(port=1025)
|
||||||
|
|
||||||
|
self.services['Django'] = hitchpython.DjangoService(
|
||||||
|
python=python_package.python,
|
||||||
|
port=8000,
|
||||||
|
version=str(self.settings.get("django_version")),
|
||||||
|
settings="config.settings.local",
|
||||||
|
needs=[self.services['Postgres'], ],
|
||||||
|
env_vars=self.settings['environment_variables'],
|
||||||
|
)
|
||||||
|
|
||||||
|
self.services['Redis'] = hitchredis.RedisService(
|
||||||
|
redis_package=redis_package,
|
||||||
|
port=16379,
|
||||||
|
)
|
||||||
|
{% if cookiecutter.celery_support == "y" %}
|
||||||
|
self.services['Celery'] = hitchpython.CeleryService(
|
||||||
|
python=python_package.python,
|
||||||
|
version="3.1.18",
|
||||||
|
app="{{cookiecutter.repo_name}}.taskapp", loglevel="INFO",
|
||||||
|
needs=[
|
||||||
|
self.services['Redis'], self.services['Django'],
|
||||||
|
],
|
||||||
|
env_vars=self.settings['environment_variables'],
|
||||||
|
)
|
||||||
|
{% endif %}
|
||||||
|
self.services['Firefox'] = hitchselenium.SeleniumService(
|
||||||
|
xvfb=self.settings.get("quiet", False),
|
||||||
|
no_libfaketime=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# import hitchcron
|
||||||
|
# self.services['Cron'] = hitchcron.CronService(
|
||||||
|
# run=self.services['Django'].manage("trigger").command,
|
||||||
|
# every=1,
|
||||||
|
# needs=[ self.services['Django'], ],
|
||||||
|
# )
|
||||||
|
|
||||||
|
self.services.startup(interactive=False)
|
||||||
|
|
||||||
|
# Configure selenium driver
|
||||||
|
self.driver = self.services['Firefox'].driver
|
||||||
|
self.driver.set_window_size(self.settings['window_size']['height'], self.settings['window_size']['width'])
|
||||||
|
self.driver.set_window_position(0, 0)
|
||||||
|
self.driver.implicitly_wait(2.0)
|
||||||
|
self.driver.accept_next_alert = True
|
||||||
|
|
||||||
|
def pause(self, message=None):
|
||||||
|
"""Stop. IPython time."""
|
||||||
|
if hasattr(self, 'services'):
|
||||||
|
self.services.start_interactive_mode()
|
||||||
|
self.ipython(message)
|
||||||
|
if hasattr(self, 'services'):
|
||||||
|
self.services.stop_interactive_mode()
|
||||||
|
|
||||||
|
def load_website(self):
|
||||||
|
"""Navigate to website in Firefox."""
|
||||||
|
self.driver.get(self.services['Django'].url())
|
||||||
|
|
||||||
|
def click(self, on):
|
||||||
|
"""Click on HTML id."""
|
||||||
|
self.driver.find_element_by_id(on).click()
|
||||||
|
|
||||||
|
def fill_form(self, **kwargs):
|
||||||
|
"""Fill in a form with id=value."""
|
||||||
|
for element, text in kwargs.items():
|
||||||
|
self.driver.find_element_by_id(element).send_keys(text)
|
||||||
|
|
||||||
|
def click_submit(self):
|
||||||
|
"""Click on a submit button if it exists."""
|
||||||
|
self.driver.find_element_by_css_selector("button[type=\"submit\"]").click()
|
||||||
|
|
||||||
|
def confirm_emails_sent(self, number):
|
||||||
|
"""Count number of emails sent by app."""
|
||||||
|
assert len(self.services['HitchSMTP'].logs.json()) == int(number)
|
||||||
|
|
||||||
|
def wait_for_email(self, containing=None):
|
||||||
|
"""Wait for, and return email."""
|
||||||
|
self.services['HitchSMTP'].logs.out.tail.until_json(
|
||||||
|
lambda email: containing in email['payload'] or containing in email['subject'],
|
||||||
|
timeout=25,
|
||||||
|
lines_back=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
def time_travel(self, days=""):
|
||||||
|
"""Make all services think that time has skipped forward."""
|
||||||
|
self.services.time_travel(days=int(days))
|
||||||
|
|
||||||
|
def on_failure(self):
|
||||||
|
"""Stop and IPython."""
|
||||||
|
if not self.settings['quiet']:
|
||||||
|
if self.settings.get("pause_on_failure", False):
|
||||||
|
self.pause(message=self.stacktrace.to_template())
|
||||||
|
|
||||||
|
def on_success(self):
|
||||||
|
"""Pause on success if enabled."""
|
||||||
|
if self.settings.get("pause_on_success", False):
|
||||||
|
self.pause(message="SUCCESS")
|
||||||
|
|
||||||
|
def tear_down(self):
|
||||||
|
"""Shut down services required to run your test."""
|
||||||
|
if hasattr(self, 'services'):
|
||||||
|
self.services.shutdown()
|
26
{{cookiecutter.repo_name}}/tests/hitchreqs.txt
Normal file
26
{{cookiecutter.repo_name}}/tests/hitchreqs.txt
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
click==4.0
|
||||||
|
colorama==0.3.3
|
||||||
|
faketime==0.9.6.3
|
||||||
|
hitchcron==0.2
|
||||||
|
hitchpostgres==0.6.1
|
||||||
|
hitchpython==0.2
|
||||||
|
hitchredis==0.4.1
|
||||||
|
hitchselenium==0.3.1
|
||||||
|
hitchserve==0.4.2
|
||||||
|
hitchsmtp==0.2.1
|
||||||
|
hitchtest==0.7
|
||||||
|
humanize==0.5.1
|
||||||
|
ipython==3.1.0
|
||||||
|
Jinja2==2.7.3
|
||||||
|
MarkupSafe==0.23
|
||||||
|
patool==1.7
|
||||||
|
psutil==3.0.0
|
||||||
|
python-build==0.2.1
|
||||||
|
pyuv==1.0.2
|
||||||
|
PyYAML==3.11
|
||||||
|
requests==2.7.0
|
||||||
|
selenium==2.46.0
|
||||||
|
six==1.9.0
|
||||||
|
tblib==1.0.1
|
||||||
|
tornado==4.2
|
||||||
|
xeger==0.3
|
59
{{cookiecutter.repo_name}}/tests/settings.yml
Normal file
59
{{cookiecutter.repo_name}}/tests/settings.yml
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
postgres_version: 9.3.9
|
||||||
|
redis_version: 2.8.4
|
||||||
|
django_version: 1.8.3
|
||||||
|
celery_version: 3.1.18
|
||||||
|
pause_on_success: false
|
||||||
|
pause_on_failure: true
|
||||||
|
startup_timeout: 45
|
||||||
|
environment_variables:
|
||||||
|
DATABASE_URL: postgres://{{cookiecutter.repo_name}}:password@127.0.0.1:15432/{{cookiecutter.repo_name}}
|
||||||
|
SECRET_KEY: cj5^uos4tfCdfghjkf5hq$9$(@-79^e9&x$3vyf#igvsfm4d=+
|
||||||
|
CELERY_BROKER_URL: redis://localhost:16379
|
||||||
|
window_size:
|
||||||
|
width: 450
|
||||||
|
height: 450
|
||||||
|
python_versions:
|
||||||
|
- 2.7.10
|
||||||
|
environment:
|
||||||
|
- approved_platforms:
|
||||||
|
- linux
|
||||||
|
- darwin
|
||||||
|
- freeports:
|
||||||
|
- 1025
|
||||||
|
- 8000
|
||||||
|
- 15432
|
||||||
|
- 16379
|
||||||
|
- brew:
|
||||||
|
- libtool
|
||||||
|
- automake
|
||||||
|
- node
|
||||||
|
- debs:
|
||||||
|
- python-setuptools
|
||||||
|
- python3-dev
|
||||||
|
- python-virtualenv
|
||||||
|
- python-pip
|
||||||
|
- firefox
|
||||||
|
- automake
|
||||||
|
- libtool
|
||||||
|
- libreadline6
|
||||||
|
- libreadline6-dev
|
||||||
|
- libreadline-dev
|
||||||
|
- libsqlite3-dev
|
||||||
|
- libpq-dev
|
||||||
|
- libxml2
|
||||||
|
- libxml2-dev
|
||||||
|
- libssl-dev
|
||||||
|
- libbz2-dev
|
||||||
|
- wget
|
||||||
|
- curl
|
||||||
|
- llvm
|
||||||
|
- graphviz-dev
|
||||||
|
- libtiff4-dev
|
||||||
|
- libjpeg8-dev
|
||||||
|
- libfreetype6-dev
|
||||||
|
- liblcms1-dev
|
||||||
|
- libwebp-dev
|
||||||
|
- zlib1g-dev
|
||||||
|
- gettext
|
||||||
|
- python-dev
|
||||||
|
- build-essential
|
10
{{cookiecutter.repo_name}}/tests/stub.test
Normal file
10
{{cookiecutter.repo_name}}/tests/stub.test
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{% raw %}{% extends "base.yml" %}
|
||||||
|
{% block test %}
|
||||||
|
- engine: engine.py:ExecutionEngine
|
||||||
|
name: Stub {{ python_version }}
|
||||||
|
preconditions:
|
||||||
|
python_version: "{{ python_version }}"
|
||||||
|
scenario:
|
||||||
|
- Load website
|
||||||
|
- Pause
|
||||||
|
{% endblock %}{% endraw %}
|
Loading…
Reference in New Issue
Block a user