diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1c1185dc081..810934bcc94 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,17 @@ .. towncrier release notes start + +Pytest 3.2.0 (unreleased) +========================= + +- New ``cache_dir`` ini option: sets a directory where stores content of cache plugin. + Default directory is ``.cache`` which is created in :ref:`rootdir `. + Directory may be relative or absolute path. If setting relative path, then directory + is created relative to :ref:`rootdir `. Additionally path may contain environment + variables, that will be expanded. + + Pytest 3.1.3 (2017-07-03) ========================= diff --git a/_pytest/cacheprovider.py b/_pytest/cacheprovider.py index 7fc08fff368..8e64f5b8dc9 100755 --- a/_pytest/cacheprovider.py +++ b/_pytest/cacheprovider.py @@ -8,13 +8,14 @@ import py import pytest import json +import os from os.path import sep as _sep, altsep as _altsep class Cache(object): def __init__(self, config): self.config = config - self._cachedir = config.rootdir.join(".cache") + self._cachedir = Cache.cache_dir_from_config(config) self.trace = config.trace.root.get("cache") if config.getvalue("cacheclear"): self.trace("clearing cachedir") @@ -22,6 +23,16 @@ def __init__(self, config): self._cachedir.remove() self._cachedir.mkdir() + @staticmethod + def cache_dir_from_config(config): + cache_dir = config.getini("cache_dir") + cache_dir = os.path.expanduser(cache_dir) + cache_dir = os.path.expandvars(cache_dir) + if os.path.isabs(cache_dir): + return py.path.local(cache_dir) + else: + return config.rootdir.join(cache_dir) + def makedir(self, name): """ return a directory path object with the given name. If the directory does not yet exist, it will be created. You can use it @@ -171,6 +182,9 @@ def pytest_addoption(parser): group.addoption( '--cache-clear', action='store_true', dest="cacheclear", help="remove all cache contents at start of test run.") + parser.addini( + "cache_dir", default='.cache', + help="cache directory path.") def pytest_cmdline_main(config): diff --git a/doc/en/cache.rst b/doc/en/cache.rst index 688b6dd0468..e4071a8f8ab 100644 --- a/doc/en/cache.rst +++ b/doc/en/cache.rst @@ -1,3 +1,5 @@ +.. _`cache_provider`: + Cache: working with cross-testrun state ======================================= diff --git a/doc/en/customize.rst b/doc/en/customize.rst index ce0a36c11a2..0e484e37df5 100644 --- a/doc/en/customize.rst +++ b/doc/en/customize.rst @@ -243,7 +243,6 @@ Builtin configuration file options from ``pytest.ini``/``tox.ini``/``setup.cfg`` of the project if any, or up to the file-system root. - .. confval:: filterwarnings .. versionadded:: 3.1 @@ -262,3 +261,14 @@ Builtin configuration file options This tells pytest to ignore deprecation warnings and turn all other warnings into errors. For more information please refer to :ref:`warnings`. + +.. confval:: cache_dir + + .. versionadded:: 3.2 + + Sets a directory where stores content of cache plugin. Default directory is + ``.cache`` which is created in :ref:`rootdir `. Directory may be + relative or absolute path. If setting relative path, then directory is created + relative to :ref:`rootdir `. Additionally path may contain environment + variables, that will be expanded. For more information about cache plugin + please refer to :ref:`cache_provider`. diff --git a/testing/test_cache.py b/testing/test_cache.py index 600b5e6d9fc..c7e92063b1a 100755 --- a/testing/test_cache.py +++ b/testing/test_cache.py @@ -1,6 +1,6 @@ from __future__ import absolute_import, division, print_function import sys - +import py import _pytest import pytest import os @@ -87,7 +87,36 @@ def test_cachefuncarg(cache): assert result.ret == 0 result.stdout.fnmatch_lines(["*1 passed*"]) - + def test_custom_rel_cache_dir(self, testdir): + rel_cache_dir = os.path.join('custom_cache_dir', 'subdir') + testdir.makeini(""" + [pytest] + cache_dir = {cache_dir} + """.format(cache_dir=rel_cache_dir)) + testdir.makepyfile(test_errored='def test_error():\n assert False') + testdir.runpytest() + assert testdir.tmpdir.join(rel_cache_dir).isdir() + + def test_custom_abs_cache_dir(self, testdir, tmpdir_factory): + tmp = str(tmpdir_factory.mktemp('tmp')) + abs_cache_dir = os.path.join(tmp, 'custom_cache_dir') + testdir.makeini(""" + [pytest] + cache_dir = {cache_dir} + """.format(cache_dir=abs_cache_dir)) + testdir.makepyfile(test_errored='def test_error():\n assert False') + testdir.runpytest() + assert py.path.local(abs_cache_dir).isdir() + + def test_custom_cache_dir_with_env_var(self, testdir, monkeypatch): + monkeypatch.setenv('env_var', 'custom_cache_dir') + testdir.makeini(""" + [pytest] + cache_dir = {cache_dir} + """.format(cache_dir='$env_var')) + testdir.makepyfile(test_errored='def test_error():\n assert False') + testdir.runpytest() + assert testdir.tmpdir.join('custom_cache_dir').isdir() def test_cache_reportheader(testdir): testdir.makepyfile("""