Coder Social home page Coder Social logo

pytest-cookies's Introduction

pytest-cookies

pytest is a mature testing framework for Python that is developed by a thriving and ever-growing community of volunteers. It uses plain assert statements and regular Python comparisons. At the core of the pytest test framework is a powerful hook-based plugin system.

pytest-cookies is a pytest plugin that comes with a cookies fixture which is a wrapper for the cookiecutter API for generating projects. It helps you verify that your template is working as expected and takes care of cleaning up after running the tests. ๐Ÿช

Installation

pytest-cookies is available for download from PyPI via pip:

pip install pytest-cookies

This will automatically install pytest and cookiecutter.

Usage

Generate a new project

The cookies.bake() method generates a new project from your template based on the default values specified in cookiecutter.json:

def test_bake_project(cookies):
    result = cookies.bake(extra_context={"repo_name": "helloworld"})

    assert result.exit_code == 0
    assert result.exception is None

    assert result.project_path.name == "helloworld"
    assert result.project_path.is_dir()

    # The `project` attribute is deprecated
    assert result.project.basename == "helloworld"
    assert result.project.isdir()

Please note that the project attribute of the returned Result class is deprecated and will be removed in a future release, please use project_path instead.

The cookies.bake() method also accepts the extra_context keyword argument that will be passed to cookiecutter. The given dictionary will override the default values of the template context, effectively allowing you to test arbitrary user input data.

For more information on injecting extra context, please check out the cookiecutter documentation.

Specify the template directory

By default cookies.bake() looks for a cookiecutter template in the current directory. This can be overridden on the command line by passing a --template parameter to pytest:

pytest --template TEMPLATE

You can customize the cookiecutter template directory from a test by passing in the optional template paramter:

@pytest.fixture
def custom_template(tmpdir):
    template = tmpdir.ensure("cookiecutter-template", dir=True)
    template.join("cookiecutter.json").write('{"repo_name": "example-project"}')

    repo_dir = template.ensure("{{cookiecutter.repo_name}}", dir=True)
    repo_dir.join("README.rst").write("{{cookiecutter.repo_name}}")

    return template


def test_bake_custom_project(cookies, custom_template):
    """Test for 'cookiecutter-template'."""
    result = cookies.bake(template=str(custom_template))

    assert result.exit_code == 0
    assert result.exception is None

    assert result.project_path.name == "example-project"
    assert result.project_path.is_dir()

Keep output directories for debugging

By default cookies removes baked projects.

However, you can pass the keep-baked-projects flag if you'd like to keep them (it won't clutter as pytest only keeps the three newest temporary directories):

pytest --keep-baked-projects

Community

Contributions are very welcome! If you encounter any problems, please file an issue along with a detailed description. Tests can be run with tox. Please make sure all of the tests are green before you submit a pull request.

You can also support the development of this project by volunteering to become a maintainer, which means you will be able to triage issues, merge pull-requests, and publish new releases. If you're interested, please submit a pull-request to add yourself to the list of maintainers and we'll get you started! ๐Ÿช

Please note that pytest-cookies is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

License

Distributed under the terms of the MIT license, pytest-cookies is free and open source software.

pytest-cookies's People

Contributors

gitter-badger avatar hackebrot avatar insspb avatar jakirkham avatar jamesmyatt avatar jayvdb avatar jsmedmar avatar jyrno42 avatar michaeljoseph avatar nedbat avatar pydanny avatar sobolevn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pytest-cookies's Issues

Run pytest-cookies with behave (BDD) - feasible?

Is there a way to use this pytest plugin in behave tests?

I had hoped that pytest we somehow "by magic" work with all its plugins, simply by doing an import pytest or something similar, but that didn't prove to be true.

I found behave-pytest via a StackOverflow answer, and hoped this would be the magic link, but again no avail.

So, is there any easy way to integrate pytest features in behave already, or do we yet need to come up with a solution that makes this happen?

Isolate environment

Redirect to tmpdir:

~/.cookiecutterrc
~/.cookiecutters/
~/.cookiecutter_replay/

[Question] Injecting a choice value with extra_context not being respected

Hello!

Firstly, thanks for the fantastic project - It's incredibly easy to use :)

I'm using Choices in a new project and while creating tests I noticed that no matter what I pass under extra_context it doesn't get picked up - Using Cookiecutter CLI works just fine (also checked the replay directory to confirm I wasn't passing bad data).

How to reproduce

  • Create a cookiecutter.json with a choice option:
{
 "project_name": "default name",
 "my_options": ["Opt1", "Opt2"]
}
  • Bake with extra_contexts
    result = cookies.bake(extra_context={
        'project_name': '--pytest-cookies--',
        'my_options': "Opt2"
    })

It will default to Opt1 even though we pass Opt2 in the extra context.

I'll do further debugging here but in case anyone can easily spot the issue (one of those days that you spend too much time looking at a problem and can't see the obvious).

Obrigado!!

pytest<6.0.0 pin prevents installation

> tox -e py38
GLOB sdist-make: /home/jayvdb/projects/pytest/pytest-cookies/setup.py
"arrow<0.14.0"py38 create: /home/jayvdb/projects/pytest/pytest-cookies/.tox/py38
py38 installdeps: pytest
py38 inst: /home/jayvdb/projects/pytest/pytest-cookies/.tox/.tmp/package/1/pytest-cookies-0.5.1.zip
ERROR: invocation failed (exit code 1), logfile: /home/jayvdb/projects/pytest/pytest-cookies/.tox/py38/log/py38-2.log
===================================================================== log start =====================================================================
Processing ./.tox/.tmp/package/1/pytest-cookies-0.5.1.zip
Collecting cookiecutter<1.8.0,>=1.4.0
  Downloading cookiecutter-1.7.2-py2.py3-none-any.whl (34 kB)
Collecting pytest<6.0.0,>=3.3.0
  Using cached pytest-5.4.3-py3-none-any.whl (248 kB)
Requirement already satisfied: six>=1.10 in ./.tox/py38/lib/python3.8/site-packages (from cookiecutter<1.8.0,>=1.4.0->pytest-cookies==0.5.1) (1.15.0)
Collecting Jinja2<3.0.0
  Using cached Jinja2-2.11.2-py2.py3-none-any.whl (125 kB)
Collecting click>=7.0
  Using cached click-7.1.2-py2.py3-none-any.whl (82 kB)
Collecting binaryornot>=0.4.4
  Using cached binaryornot-0.4.4-py2.py3-none-any.whl (9.0 kB)
ERROR: Could not find a version that satisfies the requirement python-slugify>=4.0.0 (from cookiecutter<1.8.0,>=1.4.0->pytest-cookies==0.5.1) (from versions: none)
ERROR: No matching distribution found for python-slugify>=4.0.0 (from cookiecutter<1.8.0,>=1.4.0->pytest-cookies==0.5.1)
WARNING: You are using pip version 20.0.2; however, version 20.2.1 is available.

How to get coverage?

Hello,

I can't get the coverage properly evaluated. Would you know how to fix this?
There are mainly two tests, one with the defaults and one with custom parameters.

Thank you,


tests/test_cookiecutter.py:

def test_defaults(cookies):
    result = cookies.bake()
    assert...

def test_customization(cookies):
    result = cookies.bake(extra_context={...})

pyproject.toml:

[tool.poetry.dependencies]
python = "^3.10"
pytest-cookies = "^0.7.0"

[tool.poetry.group.test.dependencies]
pytest = "^7.4.2"
pytest-cov = "^4.1.0"
pytest-httpserver = "^1.0.8"
coverage = {extras = ["toml"], version = "^6.5.0"}
pytest-mock = "^3.11.1"

[tool.pytest.ini_options]
log_cli = true
minversion = "6.0"
addopts = """
  --cov-report html:build/coverage-html
  --cov-report xml:build/coverage.xml
  --cov-report term
  --cov=hooks
  --cov-branch
"""
testpaths = ["tests"]
$ poetry run pytest
platform linux -- Python 3.10.10, pytest-7.4.4, pluggy-1.5.0
rootdir: ...
configfile: pyproject.toml
testpaths: tests
plugins: mock-3.14.0, cookies-0.7.0, cov-4.1.0, pytest_httpserver-1.0.10
collected 2 items                                                                                                                                                                                                                                                                        

tests/test_cookiecutter.py::test_defaults PASSED [ 50%]
tests/test_cookiecutter.py::test_customization PASSED [100%]
.../.cache/pypoetry/virtualenvs/cookiecutter-sonar--COI_dO4-py3.10/lib/python3.10/site-packages/coverage/control.py:801: CoverageWarning: No data was collected. (no-data-collected)
  self._warn("No data was collected.", slug="no-data-collected")


---------- coverage: platform linux, python 3.10.10-final-0 ----------
Name                        Stmts   Miss  Cover
-----------------------------------------------
hooks/post_gen_project.py      33     33     0%
hooks/pre_gen_project.py        0      0   100%
-----------------------------------------------
TOTAL                          33     33     0%

Creating a scaffold and trying to test json variables i set in hooks

I had a question, hope this is an okay place to post, I'm generating a scaffold and currently using a choice selector to determine some cookiecutter options applied later on via a pre gen hook. noticed they don't show up in the context which shows the cookiecutter.json, was wondering if there is a way to go about testing they are being applied properly.

General example of what i'm working with
cookiecutter.json
{ 'project_name': 'my project',
'directory_name': "{{cookiecutter.adapter_name.lower().replace(' ','')}}",
'source': ["sql","base"]
}`

pre_gen_project.py
{% if cookiecutter.source == "sql" %} {{ cookiecutter.update({ "adapter":"SQL","connection": "SQLManager"}) }} {% else %} {{ cookiecutter.update({"adapter":"Base","connection":"BaseManager"}) }} {% endif %}

Testing against samples of provided values, lots of them

Hi!

Thank you for pytest-cookies ๐Ÿ‘

I sometimes happen to write tests that needs the rendered context in order to test my hooks (for instance).

  • Given the user provided value some value for given prompt
  • When the template is rendered
  • Then the rendered project should ...

Since the context is not available in the cookies fixture I though it might be a nice addition.

You might not agree or have the time to add this to pytest-cookies, so let me share a gist showing an example of how this could be achieved.

Also, this could help reduce test run time in some cases

Request to support pytest>=5.0.0

I tried with pytest 5.1.2, it works in my case. But I received an error:

ERROR: pytest-cookies 0.4.0 has requirement pytest<5.0.0,>=3.3.0, but you'll have pytest 5.1.2 which is incompatible.

Will this project support pytest>=5.0.0 in the future?

Pytest-cookies fails on Windows (YAML config erroneous)

The YAML config is built by simple string formatting in https://github.com/hackebrot/pytest-cookies/blob/master/src/pytest_cookies/plugin.py

But since on Windows, filepaths use backslashes, this makes an invalid YAML file with wrong escape sequences :

while scanning a double-quoted scalar
  in "C:\Users\Pascal\AppData\Local\Temp\pytest-of-Pascal\pytest-67\user_dir0\config", line 2, column 20
expected escape sequence of 8 hexadecimal numbers, but found 's'
  in "C:\Users\Pascal\AppData\Local\Temp\pytest-of-Pascal\pytest-67\user_dir0\config", line 2, column 25

So this config should be dumped with a proper YAML parser.

For some reason, all works with old cookiecutter==1.7.2, probably the parser it uses is different

Request to support arrow>= 0.15.7

Hi, the latest version of cookiecutter installed by pip (cookiecutter==1.7.2) uses arrow==0.15.7.

Do you see any inconvenience in upgrading the dependency?

If you agree on it, I don't mind doing it.

Thanks

--keep-baked-projects option missing

I noticed a useful debugging option in the README for pytest --keep-baked-projects but I see this is not part of the latest release. Can we please get a new release on pypi?

Create documentation around cookies_session

Until diving into the code, I wasn't sure how to persist the cookiecutter sessions throughout multiple test cases.

I've noticed larger packages that use this don't use cookies session which I think would increase the performance of their test suites.

It seems that there is no documentation that this feature exists or how to use it.

Also the doc string on that feature is the same as cookies. Th e assumption is that this feature was a copy/paste with some modifications.

I would like to add documentation around cookies session as well as update the docstring.

API to check directory stucture

I am thinking about something similar to pytest's testdir but for files and directories:

result.stdout.fnmatch_lines([
    "*tmpdir*",
    "*temporary directory*",
])

Run test scenarios with pytest-cookies

I'm trying to run test scenarios with pytest as described in the pytest docs. It seems that this interferes with the pytest-cookies plugin, though:

# -- content of: tests/test_project_generation.py

class TestCookiecutterScenarios(object):
    scenarios = [
        ('travis', {
            'vcs_platform': 'GitHub.com',
            'vcs_account': 'painless-software',
            'vcs_remote': '[email protected]:painless-software/myproject.git',
            'ci_service': '.travis.yml',
            'tests': 'flake8,pylint,py27,py34,py35,pypy',
        }),
        # ...,
    ]

    def test_generate_project(self, cookies, **kwargs):
        cookie_params = dict(**kwargs)
        result = cookies.bake(extra_context=cookie_params)
        # ...

Running py.test (tox -e py35 in my setup) on this code results in:

========================================== ERRORS ===========================================
_____________________ ERROR collecting tests/test_project_generation.py _____________________
tests/test_project_generation.py:25: in pytest_generate_tests
    metafunc.parametrize(argnames, argvalues, ids=idlist, scope="class")
.tox/py35/lib/python3.5/site-packages/_pytest/python.py:813: in parametrize
    self.function, name, arg))
E   ValueError: <function TestCookiecutterScenarios.test_generate_project at 0x7efeed1d2840> uses no argument 'vcs_platform'
!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!

The "vcs_platform" argument that is said to be missing is the first element of the argnames list of the pytest_generate_tests function from the scenarios implementation.

It looks like the first dictionary key is eaten up by the cookies argument of test_generate_project. How do I fix that correctly?

conda-forge/linux/python 3.7 package?

There does not appear to be a python 3.7 package for linux on conda-forge. Would it be possible/easy to add one, and/or what would be the process to do so?

Thanks,

Andy

Session-scoped baking?

I would like to bake my cookiecutter a few different ways, and run "pip-tools compile" in each of them, and then run some tests on the results. Since pip-tools is slow, I would like to bake the cookie in a parametrized session-scoped fixture, and then use the results in the tests.

I tried this:

configurations = [
    pytest.param({"app_name": "plain"}, id="no models"),
    pytest.param({"models": "ChocolateChip,Zimsterne", "app_name": "cookies"}, id="two models"),
]

@pytest.fixture(params=configurations, scope="session")
def options_baked(cookies, request):
    result = cookies.bake(extra_context=request.param)
    with change_directory_to(str(result.project)):
        yield request.param

def test_quality(options_baked):
    # ... check things about the files in the current directory ...

But this fails with:

ScopeMismatch: You tried to access the 'function' scoped fixture 'cookies' with a 'session' scoped request object, involved factories

Maybe I'm missing something simple. Is there a way to use the cookies fixture at session scope?

Switch to Contributor Covenant

Hey there! ๐Ÿ‘‹

I would like to switch the pytest-cookies Code of Conduct to the Contributor Covenant and put my email for any reports of abusive, harassing, or otherwise unacceptable behavior.

You have contributed to this project. Do you have any objections to this? If not, please tick the box. I'll merge a PR to change the Code of Conduct if I don't hear from you in a week's time.

Thanks again for your contributions to pytest-cookies! ๐Ÿ™‡

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.