Skip to content

Commit 36ea63e

Browse files
committed
Add options for setting additional arguments to the tests
It adds: - ini configuration cpp_arguments - command line option --cpp-arguments
1 parent 7c93b8f commit 36ea63e

9 files changed

Lines changed: 196 additions & 15 deletions

File tree

README.rst

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Usage
4242
=====
4343

4444
Once installed, when py.test runs it will search and run tests
45-
founds in executable files, detecting if the suites are
45+
found in executable files, detecting if the suites are
4646
Google or Boost tests automatically.
4747

4848
You can configure which files are tested for suites by using the ``cpp_files``
@@ -55,6 +55,22 @@ ini configuration:
5555
5656
By default matches ``test_*`` and ``*_test`` executable files.
5757

58+
Additional arguments to the C++ tests can be provided with the option
59+
``--cpp-arguments`` or with the ``cpp_arguments`` ini configuration.
60+
For example:
61+
62+
.. code-block:: ini
63+
64+
[pytest]
65+
cpp_arguments=-v --log-dir=logs
66+
67+
Or the same with the command line option:
68+
69+
.. code-block:: console
70+
71+
$ pytest --cpp-arguments='-v --log-dir=logs'
72+
73+
5874
Requirements
5975
============
6076

pytest_cpp/boost.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def list_tests(self, executable):
2828
# inside the executable, so the test_id is a dummy placeholder :(
2929
return [os.path.basename(os.path.splitext(executable)[0])]
3030

31-
def run_test(self, executable, test_id):
31+
def run_test(self, executable, test_id, test_args=()):
3232

3333
def read_file(name):
3434
try:
@@ -46,6 +46,7 @@ def read_file(name):
4646
'--log_sink=%s' % log_xml,
4747
'--report_sink=%s' % report_xml,
4848
]
49+
args.extend(test_args)
4950
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
5051
stdout, _ = p.communicate()
5152

pytest_cpp/google.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,14 @@ def strip_comment(x):
5353
result.append(test_suite + strip_comment(line).strip())
5454
return result
5555

56-
def run_test(self, executable, test_id):
56+
def run_test(self, executable, test_id, test_args=()):
5757
xml_filename = self._get_temp_xml_filename()
5858
args = [
5959
executable,
6060
'--gtest_filter=' + test_id,
6161
'--gtest_output=xml:%s' % xml_filename,
6262
]
63+
args.extend(test_args)
6364
try:
6465
subprocess.check_output(args,
6566
stderr=subprocess.STDOUT,

pytest_cpp/plugin.py

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
import fnmatch
21
import os
32
import stat
3+
44
import pytest
5-
from pytest_cpp.boost import BoostTestFacade
65

6+
from pytest_cpp.boost import BoostTestFacade
77
from pytest_cpp.error import CppFailureRepr, CppFailureError
8-
98
from pytest_cpp.google import GoogleTestFacade
109

1110
FACADES = [GoogleTestFacade, BoostTestFacade]
1211
DEFAULT_MASKS = ('test_*', '*_test')
1312

13+
_ARGUMENTS = 'cpp_arguments'
14+
1415

1516
def pytest_collect_file(parent, path):
1617
try:
@@ -20,7 +21,16 @@ def pytest_collect_file(parent, path):
2021
is_executable = False
2122
if not is_executable:
2223
return
23-
masks = parent.config.getini('cpp_files') or DEFAULT_MASKS
24+
25+
config = parent.config
26+
masks = config.getini('cpp_files') or DEFAULT_MASKS
27+
28+
test_args = config.getoption(_ARGUMENTS)
29+
if test_args:
30+
test_args = test_args.split()
31+
else:
32+
test_args = config.getini(_ARGUMENTS) or ()
33+
2434
if not parent.session.isinitpath(path):
2535
for pat in masks:
2636
if path.fnmatch(pat):
@@ -29,32 +39,43 @@ def pytest_collect_file(parent, path):
2939
return
3040
for facade_class in FACADES:
3141
if facade_class.is_test_suite(str(path)):
32-
return CppFile(path, parent, facade_class())
42+
return CppFile(path, parent, facade_class(), test_args)
3343

3444

3545
def pytest_addoption(parser):
3646
parser.addini("cpp_files", type="args",
3747
default=DEFAULT_MASKS,
3848
help="glob-style file patterns for C++ test module discovery")
49+
parser.addini(_ARGUMENTS,
50+
type='args',
51+
default='',
52+
help='Additional arguments for test executables')
53+
54+
group = parser.getgroup('cpp tests')
55+
group.addoption('--cpp-arguments', help='Additional test arguments')
3956

4057

4158
class CppFile(pytest.File):
42-
def __init__(self, path, parent, facade):
59+
def __init__(self, path, parent, facade, arguments):
4360
pytest.File.__init__(self, path, parent)
4461
self.facade = facade
62+
self._arguments = arguments
4563

4664
def collect(self):
4765
for test_id in self.facade.list_tests(str(self.fspath)):
48-
yield CppItem(test_id, self, self.facade)
66+
yield CppItem(test_id, self, self.facade, self._arguments)
4967

5068

5169
class CppItem(pytest.Item):
52-
def __init__(self, name, collector, facade):
70+
def __init__(self, name, collector, facade, arguments):
5371
pytest.Item.__init__(self, name, collector)
5472
self.facade = facade
73+
self._arguments = arguments
5574

5675
def runtest(self):
57-
failures = self.facade.run_test(str(self.fspath), self.name)
76+
failures = self.facade.run_test(str(self.fspath),
77+
self.name,
78+
self._arguments)
5879
if failures:
5980
raise CppFailureError(failures)
6081

@@ -65,6 +86,3 @@ def repr_failure(self, excinfo):
6586

6687
def reportinfo(self):
6788
return self.fspath, 0, self.name
68-
69-
70-

tests/SConstruct

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ genv = env.Clone(LIBS=['gtest'] + LIBS)
1919
Export('env genv')
2020

2121
genv.Program('gtest.cpp')
22+
genv.Program('gtest_args.cpp')
2223

2324
boost_files = [
2425
'boost_success.cpp',
2526
'boost_failure.cpp',
2627
'boost_fatal_error.cpp',
2728
'boost_error.cpp',
2829
'boost_fixture_setup_error.cpp',
30+
'boost_one_argument.cpp',
31+
'boost_two_arguments.cpp'
2932
]
3033

3134
for filename in boost_files:

tests/boost_one_argument.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#define BOOST_TEST_MODULE TestOneArgument
2+
#include <boost/test/included/unit_test.hpp>
3+
4+
BOOST_AUTO_TEST_CASE(one_argument)
5+
{
6+
int argc = boost::unit_test::framework::master_test_suite().argc;
7+
char **argv = boost::unit_test::framework::master_test_suite().argv;
8+
9+
BOOST_CHECK( argc == 2 );
10+
BOOST_CHECK_EQUAL(argv[1], "argument1");
11+
}

tests/boost_two_arguments.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#define BOOST_TEST_MODULE TestTwoArguments
2+
#include <boost/test/included/unit_test.hpp>
3+
4+
BOOST_AUTO_TEST_CASE(two_arguments)
5+
{
6+
int argc = boost::unit_test::framework::master_test_suite().argc;
7+
char **argv = boost::unit_test::framework::master_test_suite().argv;
8+
9+
BOOST_CHECK( argc == 3 );
10+
BOOST_CHECK_EQUAL(argv[1], "argument1");
11+
BOOST_CHECK_EQUAL(argv[2], "argument2");
12+
}

tests/gtest_args.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "gtest/gtest.h"
2+
3+
namespace {
4+
int argsNumber;
5+
char **args;
6+
7+
TEST(ArgsTest, one_argument) {
8+
EXPECT_EQ(2, argsNumber);
9+
EXPECT_STREQ("argument1", args[1]);
10+
}
11+
12+
TEST(ArgsTest, two_arguments) {
13+
EXPECT_EQ(3, argsNumber);
14+
EXPECT_STREQ("argument1", args[1]);
15+
EXPECT_STREQ("argument2", args[2]);
16+
}
17+
} // namespace
18+
19+
int main(int argc, char **argv) {
20+
::testing::InitGoogleTest(&argc, argv);
21+
argsNumber = argc;
22+
args = argv;
23+
return RUN_ALL_TESTS();
24+
}

tests/test_pytest_cpp.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,101 @@ def test_cpp_files_option(testdir, exes):
260260
assert len(result.matchreport(exes.exe_name('gtest')).result) == 4
261261

262262

263+
def test_google_one_argument(testdir, exes):
264+
testdir.makeini('''
265+
[pytest]
266+
cpp_arguments = argument1
267+
''')
268+
269+
result = testdir.inline_run(exes.get('gtest_args'),
270+
'-k',
271+
'ArgsTest.one_argument')
272+
assert_outcomes(result,
273+
[('ArgsTest.one_argument', 'passed')])
274+
275+
276+
def test_google_two_arguments(testdir, exes):
277+
testdir.makeini('''
278+
[pytest]
279+
cpp_arguments = argument1 argument2
280+
''')
281+
282+
result = testdir.inline_run(exes.get('gtest_args'),
283+
'-k',
284+
'ArgsTest.two_arguments')
285+
assert_outcomes(result,
286+
[('ArgsTest.two_arguments', 'passed')])
287+
288+
289+
def test_google_one_argument_via_option(testdir, exes):
290+
result = testdir.inline_run(exes.get('gtest_args'),
291+
'-k',
292+
'ArgsTest.one_argument',
293+
'--cpp-arguments', 'argument1')
294+
assert_outcomes(result,
295+
[('ArgsTest.one_argument', 'passed')])
296+
297+
298+
def test_google_two_arguments_via_option(testdir, exes):
299+
result = testdir.inline_run(exes.get('gtest_args'),
300+
'-k',
301+
'ArgsTest.two_arguments',
302+
'--cpp-arguments',
303+
'argument1 argument2')
304+
assert_outcomes(result,
305+
[('ArgsTest.two_arguments', 'passed')])
306+
307+
308+
def test_argument_option_priority(testdir, exes):
309+
testdir.makeini('''
310+
[pytest]
311+
cpp_arguments = argument2
312+
''')
313+
result = testdir.inline_run(exes.get('gtest_args'),
314+
'-k',
315+
'ArgsTest.one_argument',
316+
'--cpp-arguments', 'argument1')
317+
assert_outcomes(result,
318+
[('ArgsTest.one_argument', 'passed')])
319+
320+
321+
def test_boost_one_argument(testdir, exes):
322+
testdir.makeini('''
323+
[pytest]
324+
cpp_arguments = argument1
325+
''')
326+
327+
result = testdir.inline_run(exes.get('boost_one_argument'))
328+
assert_outcomes(result,
329+
[('boost_one_argument', 'passed')])
330+
331+
332+
def test_boost_two_arguments(testdir, exes):
333+
testdir.makeini('''
334+
[pytest]
335+
cpp_arguments = argument1 argument2
336+
''')
337+
338+
result = testdir.inline_run(exes.get('boost_two_arguments'))
339+
assert_outcomes(result,
340+
[('boost_two_arguments', 'passed')])
341+
342+
343+
def test_boost_one_argument_via_option(testdir, exes):
344+
result = testdir.inline_run(exes.get('boost_one_argument'),
345+
'--cpp-arguments',
346+
'argument1')
347+
assert_outcomes(result,
348+
[('boost_one_argument', 'passed')])
349+
350+
351+
def test_boost_two_arguments_via_option(testdir, exes):
352+
result = testdir.inline_run(exes.get('boost_two_arguments'),
353+
'--cpp-arguments=argument1 argument2')
354+
assert_outcomes(result,
355+
[('boost_two_arguments', 'passed')])
356+
357+
263358
def test_passing_files_directly_in_command_line(testdir, exes):
264359
f = exes.get('boost_success')
265360
result = testdir.runpytest(f)

0 commit comments

Comments
 (0)