Merge pull request #295 from crdoconnor/master

Added support for the Hitch integration testing framework.
This commit is contained in:
Daniel Greenfeld 2015-08-12 11:41:17 -07:00
commit 0d68abcc39
8 changed files with 318 additions and 1 deletions

View 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}'"

View File

@ -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.

View File

@ -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

View File

@ -0,0 +1,4 @@
{% raw %}{% for python_version in python_versions %}
{% block test scoped %}
{% endblock %}
{% endfor %}{% endraw %}

View 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()

View 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

View 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

View 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 %}