Hitch : Updates to the default framework template - to accomodate new features, rationalized features and bug fixes.

This commit is contained in:
Colm O'Connor 2015-10-20 16:15:50 +08:00
parent c98934d7d5
commit cc98785734
14 changed files with 131 additions and 105 deletions

View File

@ -58,3 +58,6 @@ node_modules/
# User-uploaded media # User-uploaded media
{{ cookiecutter.repo_name }}/media/ {{ cookiecutter.repo_name }}/media/
# Hitch directory
tests/.hitch

View File

@ -0,0 +1,21 @@
# Global settings for your hitch tests
failfast: true
xvfb: false
pause_on_success: false
pause_on_failure: false
startup_timeout: 45
shutdown_timeout: 5
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
DJANGO_EMAIL_BACKEND: django.core.mail.backends.smtp.EmailBackend
window_size:
width: 1024
height: 768
python_version: {% if cookiecutter.use_python2 == 'n' %}3.5.0{% else %}2.7.10{% endif %}
environment:
- approved_platforms:
- linux
- darwin

View File

@ -0,0 +1,15 @@
# Continuous integration settings for your tests
#
# Run with : hitch test . --settings ci.settings
#
# * Does not stop test run on first failure.
# * Firefox is run headless.
# * Start up timeout is higher (CI machines are not always powerful)
failfast: false
xvfb: true
startup_timeout: 60
# Comment out in Jenkins or other CI environments that don't print
# color characters correctly:
# colorless: true

View File

@ -19,30 +19,25 @@ class ExecutionEngine(hitchtest.ExecutionEngine):
def set_up(self): def set_up(self):
"""Ensure virtualenv present, then run all services.""" """Ensure virtualenv present, then run all services."""
python_package = hitchpython.PythonPackage( python_package = hitchpython.PythonPackage(
python_version=self.preconditions['python_version'] python_version=self.settings['python_version']
) )
python_package.build() python_package.build()
python_package.verify()
call([ call([
python_package.pip, "install", "-r", python_package.pip, "install", "-r",
path.join(PROJECT_DIRECTORY, "requirements/local.txt") path.join(PROJECT_DIRECTORY, "requirements/local.txt")
]) ])
postgres_package = hitchpostgres.PostgresPackage( postgres_package = hitchpostgres.PostgresPackage()
version=self.settings["postgres_version"],
)
postgres_package.build() postgres_package.build()
postgres_package.verify()
redis_package = hitchredis.RedisPackage(version="2.8.4") redis_package = hitchredis.RedisPackage()
redis_package.build() redis_package.build()
redis_package.verify()
self.services = hitchserve.ServiceBundle( self.services = hitchserve.ServiceBundle(
project_directory=PROJECT_DIRECTORY, project_directory=PROJECT_DIRECTORY,
startup_timeout=float(self.settings["startup_timeout"]), startup_timeout=float(self.settings["startup_timeout"]),
shutdown_timeout=5.0, shutdown_timeout=float(self.settings["shutdown_timeout"]),
) )
postgres_user = hitchpostgres.PostgresUser("{{cookiecutter.repo_name}}", "password") postgres_user = hitchpostgres.PostgresUser("{{cookiecutter.repo_name}}", "password")
@ -58,7 +53,6 @@ class ExecutionEngine(hitchtest.ExecutionEngine):
self.services['Django'] = hitchpython.DjangoService( self.services['Django'] = hitchpython.DjangoService(
python=python_package.python, python=python_package.python,
port=8000, port=8000,
version=str(self.settings.get("django_version")),
settings="config.settings.local", settings="config.settings.local",
needs=[self.services['Postgres'], ], needs=[self.services['Postgres'], ],
env_vars=self.settings['environment_variables'], env_vars=self.settings['environment_variables'],
@ -71,7 +65,6 @@ class ExecutionEngine(hitchtest.ExecutionEngine):
{% if cookiecutter.celery_support == "y" %} {% if cookiecutter.celery_support == "y" %}
self.services['Celery'] = hitchpython.CeleryService( self.services['Celery'] = hitchpython.CeleryService(
python=python_package.python, python=python_package.python,
version="3.1.18",
app="{{cookiecutter.repo_name}}.taskapp", loglevel="INFO", app="{{cookiecutter.repo_name}}.taskapp", loglevel="INFO",
needs=[ needs=[
self.services['Redis'], self.services['Django'], self.services['Redis'], self.services['Django'],
@ -80,7 +73,7 @@ class ExecutionEngine(hitchtest.ExecutionEngine):
) )
{% endif %} {% endif %}
self.services['Firefox'] = hitchselenium.SeleniumService( self.services['Firefox'] = hitchselenium.SeleniumService(
xvfb=self.settings.get("quiet", False), xvfb=self.settings.get("xvfb", False),
no_libfaketime=True, no_libfaketime=True,
) )
@ -93,8 +86,22 @@ class ExecutionEngine(hitchtest.ExecutionEngine):
self.services.startup(interactive=False) self.services.startup(interactive=False)
# Configure selenium driver # Docs : https://hitchtest.readthedocs.org/en/latest/plugins/hitchselenium.html
self.driver = self.services['Firefox'].driver self.driver = self.services['Firefox'].driver
self.webapp = hitchselenium.SeleniumStepLibrary(
selenium_webdriver=self.driver,
wait_for_timeout=5,
)
# Add selenium steps
self.click = self.webapp.click
self.wait_to_appear = self.webapp.wait_to_appear
self.wait_to_contain = self.webapp.wait_to_contain
self.wait_for_any_to_contain = self.webapp.wait_for_any_to_contain
self.click_and_dont_wait_for_page_load = self.webapp.click_and_dont_wait_for_page_load
# Configure selenium driver
self.driver.set_window_size(self.settings['window_size']['height'], self.settings['window_size']['width']) self.driver.set_window_size(self.settings['window_size']['height'], self.settings['window_size']['width'])
self.driver.set_window_position(0, 0) self.driver.set_window_position(0, 0)
self.driver.implicitly_wait(2.0) self.driver.implicitly_wait(2.0)
@ -112,23 +119,21 @@ class ExecutionEngine(hitchtest.ExecutionEngine):
"""Navigate to website in Firefox.""" """Navigate to website in Firefox."""
self.driver.get(self.services['Django'].url()) 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): def fill_form(self, **kwargs):
"""Fill in a form with id=value.""" """Fill in a form with id=value."""
for element, text in kwargs.items(): for element, text in kwargs.items():
self.driver.find_element_by_id(element).send_keys(text) 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): def confirm_emails_sent(self, number):
"""Count number of emails sent by app.""" """Count number of emails sent by app."""
assert len(self.services['HitchSMTP'].logs.json()) == int(number) assert len(self.services['HitchSMTP'].logs.json()) == int(number)
def click_on_link_in_last_email(self, which=1):
"""Click on the nth link in the last email sent."""
self.driver.get(
self.services['HitchSMTP'].logs.json()[-1]['links'][which - 1]
)
def wait_for_email(self, containing=None): def wait_for_email(self, containing=None):
"""Wait for, and return email.""" """Wait for, and return email."""
self.services['HitchSMTP'].logs.out.tail.until_json( self.services['HitchSMTP'].logs.out.tail.until_json(

View File

@ -1,26 +1,39 @@
click==5.1 click==5.1
colorama==0.3.3 colorama==0.3.3
decorator==4.0.4
docopt==0.6.2
faketime==0.9.6.3 faketime==0.9.6.3
hitchcron==0.2 hitchcron==0.2
hitchpostgres==0.6.3 hitchpostgres==0.6.7
hitchpython==0.3.8 hitchpython==0.5.0
hitchredis==0.4.3 hitchredis==0.4.5
hitchselenium==0.4.5 hitchselenium==0.4.8
hitchserve==0.4.5 hitchserve==0.4.5
hitchsmtp==0.2.1 hitchsmtp==0.2.1
hitchtest==0.8.0 hitchsystem==0.1.1
hitchtest==0.9.2
humanize==0.5.1 humanize==0.5.1
ipython==4.0.0 ipython==4.0.0
ipython-genutils==0.1.0
Jinja2==2.8 Jinja2==2.8
MarkupSafe==0.23 MarkupSafe==0.23
path.py==8.1.2
patool==1.8 patool==1.8
pexpect==4.0.1
pickleshare==0.5
psutil==3.2.2 psutil==3.2.2
python-build==0.2.3 ptyprocess==0.5
pykwalify==1.5.0
python-build==0.2.5
python-dateutil==2.4.2
pyuv==1.2.0 pyuv==1.2.0
PyYAML==3.11 PyYAML==3.11
requests==2.7.0 requests==2.8.1
selenium==2.47.3 selenium==2.48.0
six==1.9.0 simplegeneric==0.8.1
six==1.10.0
tblib==1.1.0 tblib==1.1.0
tornado==4.2.1 tornado==4.2.1
traitlets==4.0.0
unixpackage==0.3.7
xeger==0.3 xeger==0.3

View File

@ -0,0 +1,19 @@
- name: Sign up and log in
scenario:
- Load website
- Click: djHideToolBarButton
- Click: sign-up-link
- Fill form:
id_username: testuser
id_email: testuser@domain.com
id_password1: password
id_password2: password
- Click: sign-up-button
- Wait for email:
containing: Please Confirm Your E-mail Address
- Click on link in last email
- Click: confirm-button
- Fill form:
id_login: testuser
id_password: password
- Click: sign-in-button

View File

@ -1,59 +0,0 @@
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

@ -1,10 +0,0 @@
{% 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 %}

View File

@ -0,0 +1,11 @@
firefox
libpq-dev
llvm
graphviz-dev
libtiff4-dev
libjpeg8-dev
libfreetype6-dev
liblcms1-dev
libwebp-dev
zlib1g-dev
gettext

View File

@ -0,0 +1,8 @@
# Test driven development settings
#
# Run with : hitch test . --settings tdd.settings
#
# Tests stop on first failure, pause and launch into IPython for debugging/interaction.
failfast: true
pause_on_failure: true

View File

@ -21,7 +21,7 @@
<form method="post" action="{% url 'account_confirm_email' confirmation.key %}"> <form method="post" action="{% url 'account_confirm_email' confirmation.key %}">
{% csrf_token %} {% csrf_token %}
<button class="submit" type="submit">{% trans 'Confirm' %}</button> <button id="confirm-button" class="submit" type="submit">{% trans 'Confirm' %}</button>
</form> </form>
{% else %} {% else %}

View File

@ -39,7 +39,7 @@
{% if redirect_field_value %} {% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" /> <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %} {% endif %}
<button class="btn btn-primary" type="submit">{% trans "Sign In" %}</button> <button id="sign-in-button" class="btn btn-primary" type="submit">{% trans "Sign In" %}</button>
<a class="button secondaryAction" href="{% url 'account_reset_password' %}">{% trans "Forgot Password?" %}</a> <a class="button secondaryAction" href="{% url 'account_reset_password' %}">{% trans "Forgot Password?" %}</a>
</form> </form>
</div> </div>

View File

@ -21,7 +21,7 @@
{% if redirect_field_value %} {% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" /> <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %} {% endif %}
<button class="btn btn-primary" type="submit">{% trans "Sign Up" %} &raquo;</button> <button id="sign-up-button" class="btn btn-primary" type="submit">{% trans "Sign Up" %} &raquo;</button>
</form> </form>
</div> </div>
</div> </div>

View File

@ -51,8 +51,8 @@
<a class="nav-link nav-item" href="{% url 'users:detail' request.user.username %}">{% trans "My Profile" %}</a> <a class="nav-link nav-item" href="{% url 'users:detail' request.user.username %}">{% trans "My Profile" %}</a>
<a class="nav-link nav-item" href="{% url 'account_logout' %}">{% trans "Logout" %}</a> <a class="nav-link nav-item" href="{% url 'account_logout' %}">{% trans "Logout" %}</a>
{% else %} {% else %}
<a class="nav-link nav-item" href="{% url 'account_signup' %}">{% trans "Sign Up" %}</a> <a id="sign-up-link" class="nav-link nav-item" href="{% url 'account_signup' %}">{% trans "Sign Up" %}</a>
<a class="nav-link nav-item" href="{% url 'account_login' %}">{% trans "Log In" %}</a> <a id="log-in-link" class="nav-link nav-item" href="{% url 'account_login' %}">{% trans "Log In" %}</a>
{% endif %} {% endif %}
</nav> </nav>
</div> </div>