Merge pull request #402 from hackebrot/use-tox-and-pytest-cookies

Use tox and pytest cookies
This commit is contained in:
Daniel Roy Greenfeld 2015-11-09 07:15:32 -08:00
commit cb8376ce2a
9 changed files with 166 additions and 114 deletions

5
.gitignore vendored
View File

@ -33,3 +33,8 @@ my_test_project/*
# Generated when running py.test for the cookiecutter-django generation tests
.cache/
# Unit test / coverage reports
.coverage
.tox
.cache

View File

@ -1,14 +1,17 @@
language: python
python:
- 3.5
- 3.4
- 2.7
sudo: false
install:
- pip install -r requirements.txt
# Config file for automatic testing at travis-ci.org
script:
- py.test
sudo: false
language: python
python: 3.5
env:
- TOX_ENV=py27
- TOX_ENV=py34
- TOX_ENV=py35
script: tox -e $TOX_ENV
install:
- pip install tox
notifications:
email:

View File

@ -9,3 +9,48 @@ Getting your pull request merged in
#. Keep it small. The smaller the pull request the more likely I'll pull it in.
#. Pull requests that fix a current issue get priority for review.
#. If you're not already in the `CONTRIBUTORS.rst` file, add yourself!
Testing
-------
Installation
~~~~~~~~~~~~
Please install `tox`_, which is a generic virtualenv management and test command line tool.
`tox`_ is available for download from `PyPI`_ via `pip`_::
$ pip install tox
It will automatically create a fresh virtual environment and install our test dependencies,
such as `pytest-cookies`_ and `flake8`_.
Run the Tests
~~~~~~~~~~~~~
Tox uses py.test under the hood, hence it supports the same syntax for selecting tests.
For further information please consult the `pytest usage docs`_.
To run all tests using various versions of python in virtualenvs defined in tox.ini, just run tox.::
$ tox
It is possible to tests with some versions of python, to do this the command
is::
$ tox -e py27,py34
Will run py.test with the python2.7, and python3.4 interpreters, for
example.
To run a particular test with tox for against your current Python version::
$ tox -e py -- -k test_default_configuration
.. _`pytest usage docs`: https://pytest.org/latest/usage.html#specifying-tests-selecting-tests
.. _`tox`: https://tox.readthedocs.org/en/latest/
.. _`pip`: https://pypi.python.org/pypi/pip/
.. _`pytest-cookies`: https://pypi.python.org/pypi/pytest-cookies/
.. _`flake8`: https://pypi.python.org/pypi/flake8/
.. _`PyPI`: https://pypi.python.org/pypi

View File

@ -14,3 +14,4 @@ pytest==2.8.2
git+git://github.com/mverteuil/pytest-ipdb.git
pep8==1.6.2
pyflakes==1.0.0
tox==2.1.1

View File

View File

@ -1,71 +0,0 @@
import os
import re
import shutil
import unittest
from os.path import exists, dirname, join
from binaryornot.check import is_binary
import sh
from cookiecutter.main import cookiecutter
class DjangoCookieTestCase(unittest.TestCase):
root_dir = dirname(dirname(__file__))
ctx = {}
destpath = None
def check_paths(self, paths):
"""
Method to check all paths have correct substitutions,
used by other tests cases
"""
# Construct the cookiecutter search pattern
pattern = "{{(\s?cookiecutter)[.](.*?)}}"
re_obj = re.compile(pattern)
# Assert that no match is found in any of the files
for path in paths:
if not is_binary(path):
for line in open(path, 'r'):
match = re_obj.search(line)
self.assertIsNone(
match,
"cookiecutter variable not replaced in {}".format(path))
def generate_project(self, extra_context=None):
ctx = {
"project_name": "My Test Project",
"repo_name": "my_test_project",
"author_name": "Test Author",
"email": "test@example.com",
"description": "A short description of the project.",
"domain_name": "example.com",
"version": "0.1.0",
"timezone": "UTC",
"now": "2015/01/13",
"year": "2015"
}
if extra_context:
assert isinstance(extra_context, dict)
ctx.update(extra_context)
self.ctx = ctx
self.destpath = join(self.root_dir, self.ctx['repo_name'])
cookiecutter(template='./', checkout=None, no_input=True, extra_context=ctx)
# Build a list containing absolute paths to the generated files
paths = [os.path.join(dirpath, file_path)
for dirpath, subdirs, files in os.walk(self.destpath)
for file_path in files]
return paths
def clean(self):
if exists(self.destpath):
shutil.rmtree(self.destpath)
sh.cd(self.root_dir)
def tearDown(self):
self.clean()

View File

@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
import os
import re
import sh
import pytest
from binaryornot.check import is_binary
PATTERN = "{{(\s?cookiecutter)[.](.*?)}}"
RE_OBJ = re.compile(PATTERN)
@pytest.fixture
def context():
return {
"project_name": "My Test Project",
"repo_name": "my_test_project",
"author_name": "Test Author",
"email": "test@example.com",
"description": "A short description of the project.",
"domain_name": "example.com",
"version": "0.1.0",
"timezone": "UTC",
"now": "2015/01/13",
"year": "2015"
}
def build_files_list(root_dir):
"""Build a list containing absolute paths to the generated files."""
return [
os.path.join(dirpath, file_path)
for dirpath, subdirs, files in os.walk(root_dir)
for file_path in files
]
def check_paths(paths):
"""Method to check all paths have correct substitutions,
used by other tests cases
"""
# Assert that no match is found in any of the files
for path in paths:
if is_binary(path):
continue
for line in open(path, 'r'):
match = RE_OBJ.search(line)
msg = "cookiecutter variable not replaced in {}"
assert match is None, msg.format(path)
def test_default_configuration(cookies, context):
result = cookies.bake(extra_context=context)
assert result.exit_code == 0
assert result.exception is None
assert result.project.basename == context['repo_name']
assert result.project.isdir()
paths = build_files_list(str(result.project))
assert paths
check_paths(paths)
@pytest.fixture(params=['use_maildump', 'use_celery', 'windows'])
def feature_context(request, context):
context.update({request.param: 'y'})
return context
def test_enabled_features(cookies, feature_context):
result = cookies.bake(extra_context=feature_context)
assert result.exit_code == 0
assert result.exception is None
assert result.project.basename == feature_context['repo_name']
assert result.project.isdir()
paths = build_files_list(str(result.project))
assert paths
check_paths(paths)
def test_flake8_compliance(cookies):
"""generated project should pass flake8"""
result = cookies.bake()
try:
sh.flake8(str(result.project))
except sh.ErrorReturnCode as e:
pytest.fail(e)

View File

@ -1,33 +0,0 @@
from __future__ import absolute_import
import sh
from .base import DjangoCookieTestCase
class TestCookiecutterSubstitution(DjangoCookieTestCase):
"""Test that all cookiecutter instances are substituted"""
def test_default_configuration(self):
# Build a list containing absolute paths to the generated files
paths = self.generate_project()
self.check_paths(paths)
def test_maildump_enabled(self):
paths = self.generate_project(extra_context={'use_maildump': 'y'})
self.check_paths(paths)
def test_celery_enabled(self):
paths = self.generate_project(extra_context={'use_celery': 'y'})
self.check_paths(paths)
def test_windows_enabled(self):
paths = self.generate_project(extra_context={'windows': 'y'})
self.check_paths(paths)
def test_flake8_compliance(self):
"""generated project should pass flake8"""
self.generate_project()
try:
sh.flake8(self.destpath)
except sh.ErrorReturnCode as e:
raise AssertionError(e)

12
tox.ini Normal file
View File

@ -0,0 +1,12 @@
[tox]
skipsdist = true
envlist = py27,py34,py35
[testenv]
passenv = LC_ALL, LANG, HOME
deps =
binaryornot
flake8
pytest-cookies
sh
commands = py.test {posargs:tests}