Skip to content

Commit 68bed00

Browse files
authored
Merge pull request pytest-dev#1667 from fengxx/feature/override_ini_option
Add --overwrite-ini ININAME=INIVALUE cli option
2 parents 13a188f + 856e6ca commit 68bed00

File tree

5 files changed

+124
-8
lines changed

5 files changed

+124
-8
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ Samuele Pedroni
100100
Steffen Allner
101101
Stephan Obermann
102102
Tareq Alayan
103+
Ted Xiao
103104
Simon Gomizelj
104105
Stefano Taschini
105106
Stefan Farmbauer

CHANGELOG.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@
7979
finalizer and has access to the fixture's result cache.
8080
Thanks `@d6e`_, `@sallner`_
8181

82+
* New cli flag ``--override-ini`` or ``-o`` that overrides values from the ini file.
83+
Example '-o xfail_strict=True'. A complete ini-options can be viewed
84+
by py.test --help. Thanks `@blueyed`_ and `@fengxx`_ for the PR
85+
8286

8387
**Changes**
8488

@@ -155,6 +159,8 @@
155159
.. _@nikratio: https://github.com/nikratio
156160
.. _@RedBeardCode: https://github.com/RedBeardCode
157161
.. _@Vogtinator: https://github.com/Vogtinator
162+
.. _@blueyed: https://github.com/blueyed
163+
.. _@fengxx: https://github.com/fengxx
158164

159165
* Fix `#1421`_: Exit tests if a collection error occurs and add
160166
``--continue-on-collection-errors`` option to restore previous behaviour.

_pytest/config.py

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,14 +1003,16 @@ def _getini(self, name):
10031003
description, type, default = self._parser._inidict[name]
10041004
except KeyError:
10051005
raise ValueError("unknown configuration value: %r" %(name,))
1006-
try:
1007-
value = self.inicfg[name]
1008-
except KeyError:
1009-
if default is not None:
1010-
return default
1011-
if type is None:
1012-
return ''
1013-
return []
1006+
value = self._get_override_ini_value(name)
1007+
if value is None:
1008+
try:
1009+
value = self.inicfg[name]
1010+
except KeyError:
1011+
if default is not None:
1012+
return default
1013+
if type is None:
1014+
return ''
1015+
return []
10141016
if type == "pathlist":
10151017
dp = py.path.local(self.inicfg.config.path).dirpath()
10161018
l = []
@@ -1041,6 +1043,20 @@ def _getconftest_pathlist(self, name, path):
10411043
l.append(relroot)
10421044
return l
10431045

1046+
def _get_override_ini_value(self, name):
1047+
value = None
1048+
# override_ini is a list of list, to support both -o foo1=bar1 foo2=bar2 and
1049+
# and -o foo1=bar1 -o foo2=bar2 options
1050+
# always use the last item if multiple value set for same ini-name,
1051+
# e.g. -o foo=bar1 -o foo=bar2 will set foo to bar2
1052+
if self.getoption("override_ini", None):
1053+
for ini_config_list in self.option.override_ini:
1054+
for ini_config in ini_config_list:
1055+
(key, user_ini_value) = ini_config.split("=", 1)
1056+
if key == name:
1057+
value = user_ini_value
1058+
return value
1059+
10441060
def getoption(self, name, default=notset, skip=False):
10451061
""" return command line option value.
10461062

_pytest/helpconfig.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ def pytest_addoption(parser):
2020
group.addoption('--debug',
2121
action="store_true", dest="debug", default=False,
2222
help="store internal tracing debug information in 'pytestdebug.log'.")
23+
# support for "--overwrite-ini ININAME=INIVALUE" to override values from the ini file
24+
# Example '-o xfail_strict=True'.
25+
group._addoption('-o', '--override-ini', nargs='*', dest="override_ini", action="append",
26+
help="overrides ini values which do not have a separate command-line flag")
2327

2428

2529
@pytest.hookimpl(hookwrapper=True)

testing/test_config.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,3 +583,92 @@ def test_with_specific_inifile(self, tmpdir):
583583
inifile = tmpdir.ensure("pytest.ini")
584584
rootdir, inifile, inicfg = determine_setup(inifile, [tmpdir])
585585
assert rootdir == tmpdir
586+
587+
class TestOverrideIniArgs:
588+
""" test --override-ini """
589+
@pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split())
590+
def test_override_ini_names(self, testdir, name):
591+
testdir.tmpdir.join(name).write(py.std.textwrap.dedent("""
592+
[pytest]
593+
custom = 1.0
594+
"""))
595+
testdir.makeconftest("""
596+
def pytest_addoption(parser):
597+
parser.addini("custom", "")
598+
""")
599+
testdir.makepyfile("""
600+
def test_pass(pytestconfig):
601+
ini_val = pytestconfig.getini("custom")
602+
print('\\ncustom_option:%s\\n' % ini_val)
603+
""")
604+
605+
result = testdir.runpytest("--override-ini", "custom=2.0", "-s")
606+
assert result.ret == 0
607+
result.stdout.fnmatch_lines([
608+
"custom_option:2.0"
609+
])
610+
611+
result = testdir.runpytest("--override-ini", "custom=2.0",
612+
"--override-ini=custom=3.0", "-s")
613+
assert result.ret == 0
614+
result.stdout.fnmatch_lines([
615+
"custom_option:3.0"
616+
])
617+
618+
619+
def test_override_ini_pathlist(self, testdir):
620+
testdir.makeconftest("""
621+
def pytest_addoption(parser):
622+
parser.addini("paths", "my new ini value", type="pathlist")
623+
""")
624+
testdir.makeini("""
625+
[pytest]
626+
paths=blah.py
627+
""")
628+
testdir.makepyfile("""
629+
import py.path
630+
def test_pathlist(pytestconfig):
631+
config_paths = pytestconfig.getini("paths")
632+
print(config_paths)
633+
for cpf in config_paths:
634+
print('\\nuser_path:%s' % cpf.basename)
635+
""")
636+
result = testdir.runpytest("--override-ini", 'paths=foo/bar1.py foo/bar2.py', "-s")
637+
result.stdout.fnmatch_lines([
638+
"user_path:bar1.py",
639+
"user_path:bar2.py"
640+
])
641+
642+
def test_override_multiple_and_default(self, testdir):
643+
testdir.makeconftest("""
644+
def pytest_addoption(parser):
645+
parser.addini("custom_option_1", "", default="o1")
646+
parser.addini("custom_option_2", "", default="o2")
647+
parser.addini("custom_option_3", "", default=False, type="bool")
648+
parser.addini("custom_option_4", "", default=True, type="bool")
649+
650+
""")
651+
testdir.makeini("""
652+
[pytest]
653+
custom_option_1=custom_option_1
654+
custom_option_2=custom_option_2
655+
""")
656+
testdir.makepyfile("""
657+
def test_multiple_options(pytestconfig):
658+
prefix="custom_option"
659+
for x in range(1,5):
660+
ini_value=pytestconfig.getini("%s_%d" % (prefix, x))
661+
print('\\nini%d:%s' % (x, ini_value))
662+
""")
663+
result = testdir.runpytest("--override-ini",
664+
'custom_option_1=fulldir=/tmp/user1',
665+
'custom_option_2=url=/tmp/user2?a=b&d=e',
666+
"-o", 'custom_option_3=True',
667+
"-o", 'custom_option_4=no',
668+
"-s")
669+
result.stdout.fnmatch_lines([
670+
"ini1:fulldir=/tmp/user1",
671+
"ini2:url=/tmp/user2?a=b&d=e",
672+
"ini3:True",
673+
"ini4:False"
674+
])

0 commit comments

Comments
 (0)