mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2024-11-30 05:24:01 +03:00
Merge pull request #402 from hackebrot/use-tox-and-pytest-cookies
Use tox and pytest cookies
This commit is contained in:
commit
cb8376ce2a
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -33,3 +33,8 @@ my_test_project/*
|
||||||
|
|
||||||
# Generated when running py.test for the cookiecutter-django generation tests
|
# Generated when running py.test for the cookiecutter-django generation tests
|
||||||
.cache/
|
.cache/
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
.coverage
|
||||||
|
.tox
|
||||||
|
.cache
|
||||||
|
|
23
.travis.yml
23
.travis.yml
|
@ -1,14 +1,17 @@
|
||||||
language: python
|
# Config file for automatic testing at travis-ci.org
|
||||||
python:
|
|
||||||
- 3.5
|
|
||||||
- 3.4
|
|
||||||
- 2.7
|
|
||||||
sudo: false
|
|
||||||
install:
|
|
||||||
- pip install -r requirements.txt
|
|
||||||
|
|
||||||
script:
|
sudo: false
|
||||||
- py.test
|
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:
|
notifications:
|
||||||
email:
|
email:
|
||||||
|
|
|
@ -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.
|
#. 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.
|
#. Pull requests that fix a current issue get priority for review.
|
||||||
#. If you're not already in the `CONTRIBUTORS.rst` file, add yourself!
|
#. 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
|
||||||
|
|
|
@ -14,3 +14,4 @@ pytest==2.8.2
|
||||||
git+git://github.com/mverteuil/pytest-ipdb.git
|
git+git://github.com/mverteuil/pytest-ipdb.git
|
||||||
pep8==1.6.2
|
pep8==1.6.2
|
||||||
pyflakes==1.0.0
|
pyflakes==1.0.0
|
||||||
|
tox==2.1.1
|
||||||
|
|
|
@ -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()
|
|
90
tests/test_cookiecutter_generation.py
Normal file
90
tests/test_cookiecutter_generation.py
Normal 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)
|
|
@ -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)
|
|
Loading…
Reference in New Issue
Block a user