-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"unrecognized arguments" or "option names already added" error when running pytest inside a Docker container using Jenkins #3097
Comments
GitMate.io thinks the contributor most likely able to help you is @nicoddemus. |
Hi @ceridwen, Hmm that's a head scratcher... from the top of my head:
|
The Jenkins script |
Hmm that's strange. Can you post the pytest output banner of the run? |
I just tried explicitly passing one of the test files on the command line, rather than letting it do discovery, and that made it work. I assume the work around now is to explicitly pass all the tests on the command line. From the docs on rootdir: "Determine the common ancestor directory for the specified args that are recognised as paths that exist in the file system. If no such paths are found, the common ancestor directory is set to the current working directory." I suspect that passing it an explicit path for one of the test files is changing the effective root directory, but I have no idea why, or why it would have arrived at the wrong root directory in the one case but not the others. |
And what if you pass |
Running it with
It's looking to me like it doesn't calculate the root directory correctly under some conditions, though I have no idea what they are. I can pass |
Both the "unrecognized arguments" error and "option names already added" ValueError come before the point when pytest would print the banner, so I don't have banners. |
Unfortunately there are no logs, but here's the function which determines the Lines 1326 to 1349 in 6fb46a0
We could add some trace functions in there. Any chance for you to use a development version inside the docker container? That would allow us to create a branch and add a bunch of trace statements to see where we get at. |
I can use a development branch inside the Docker container with pip's ability to pull from Git during dependency installation, if you create the branch. The only issue might be that because of the way pytest is currently resetting the root logger's level, with pytest 3.3 there's a tremendous amount of log-spam from my dependencies---I think the root directory determination occurs before the log-spam, though, so I can work around it. |
@ceridwen you might set Lines 189 to 197 in 6fb46a0
You will need to pass |
I took your suggestion and put some tracing in a branch. def determine_setup(inifile, args, warnfunc=None, trace=None):
dirs = get_dirs_from_args(args)
trace("initial dirs %s" % dirs)
if inifile:
iniconfig = py.iniconfig.IniConfig(inifile)
try:
inicfg = iniconfig["pytest"]
except KeyError:
inicfg = None
rootdir = get_common_ancestor(dirs)
trace("inifile found, %s" % rootdir)
else:
ancestor = get_common_ancestor(dirs)
trace("inifile not found, %s" % ancestor)
rootdir, inifile, inicfg = getcfg([ancestor], warnfunc=warnfunc)
trace("%s %s" % (rootdir, inicfg))
if rootdir is None:
trace("rootdir is None")
for rootdir in ancestor.parts(reverse=True):
trace("Try rootdir, %s" % rootdir)
if rootdir.join("setup.py").exists():
break
else:
rootdir, inifile, inicfg = getcfg(dirs, warnfunc=warnfunc)
trace("Via inicfg rootdir %s" % rootdir)
if rootdir is None:
rootdir = get_common_ancestor([py.path.local(), ancestor])
trace("Common ancestor, %s" % rootdir)
is_fs_root = os.path.splitdrive(str(rootdir))[1] == '/'
if is_fs_root:
rootdir = ancestor
trace("Final rootdir %s" % rootdir)
return rootdir, inifile, inicfg or {} With this in place, this is what the relevant log sections looks:
I don't have the first clue has to how that secrets file ends up being passed into determine_setup. I suspect but don't know that it's the file that I'm passing to pytest using
Pytest believes that its arguments are:
It looks like the command parsing might be the issue here. Have any idea what the problem is? |
I tried passing the arguments using |
I've been digging in the issue tracker because this problem seems familiar: #961, #1435, #906. I think the cause is that the new options are being configured by a Not sure if this can be fixed, because pytest can't know if |
I think I understand the issue now. I think it might be worth discussing whether there's a more transparent way to handle command-line options for pytest, like maybe splitting out command-line options into their own file that's loaded eagerly? That said, this is also a documentation problem, because the existing documentation (https://docs.pytest.org/en/latest/example/simple.html, https://docs.pytest.org/en/latest/example/parametrize.html, https://docs.pytest.org/en/latest/example/markers.html) uses |
Definitely agree on the documentation problem. I agree that we should discuss how we can better handle options from |
I am also running a Docker container on a Jenkins agent and have encountered this issue. The docker statement looks roughly like this:
inside that script, I do something like this:
I am seeing the problem described in this ticket about 50% of the time. Not sure what I should do. |
This is a complicated set up, so bear with me.
I am trying to create a Jenkins pipeline job to run Pytest on Jenkins inside a Docker container. As far as I can tell, when Jenkins starts a Docker container, it does so with the working directory of that container set to a directory on the Jenkins filesystem, under /var/jenkins_home/<job name>/ by default. Thus, running the tests requires:
Because Jenkins passes job parameters as environment variables and some other probably-not-relevant reasons, I need to use a front-end script, run_tests.py, to turn those variables into command-line arguments that pytest can understand. run_tests.py then calls pytest.main().
Here, pytest_args are arguments for pytest itself like
-s
,-k
, or--tb=<type>
. test_args are command-line arguments that I have configured in conftest.py using pytest_addoption() : these are the arguments created from environment variables. The layout of the project looks like:This setup works outside Jenkins: I cd to test_automation/, run run_tests.py, it finds conftest.py, and everything is happy. When I run the Jenkins job that's supposedly executing this same steps with PYTEST_DEBUG set:
Here, the "..." for the args stands for all the arguments in the first two cases, including the pytest-specific ones, and only the arguments configured in conftest.py for the unrecognized arguments, the last case. From looking at the logs for this same configuration that works outside Jenkins, I know that the pytest_load_initial_conftests log should look like:
It looks a lot like pytest is not finding my conftest.py file, even though it's in the root directory (with respect to how pytest is being run). However, if I have Jenkins run
python3 -m pytest --help
in the same directory, with everything else the same, pytest will correctly process conftest.py and display the options that are configured there under thecustom options:
heading. I also tried manually forcing pytest to load conftest.py using-p
. When I do that, pytest crashes with a traceback that suggests that conftest.py is already loaded:I tried passing the --debug option to pytest, but it also crashed with this traceback, so it didn't give me any more information.
I'm using Docker for Mac to run Docker on Mac OS X 10.12.6. (Docker for Mac uses Virtualbox to create a VM on Mac OS X.) Docker is version Version 17.09.1-ce-mac42 (21090).
Jenkins is also running in a Docker container, and from what I see the Docker socket is mounted inside Jenkins, so there's only one Docker instance running. Jenkins is version 2.89.2.
Is there anything else I can do to figure out what's going on here? I haven't been able to replicate the bug anywhere outside a Jenkins job. Even when I have Jenkins start the container, then use docker exec to log into, I can still run run_tests.py and it doesn't complain about unrecognized arguments.
The text was updated successfully, but these errors were encountered: