I have a pytest setup with the following config file I use for integration tests:
[pytest]
addopts = -p no:python -p no:random-order --tb=short
junit_suite_name = Integration
filterwarnings =
ignore::DeprecationWarning
The aim is to not load the random-order plugin. When running locally, I get this as the output:
$ pytest -c pytest-integration.ini --junitxml=integration-tests.xml tests/integration/
======================= test session starts ===========================
platform darwin -- Python 3.6.4, pytest-3.7.2, py-1.7.0, pluggy-0.8.0
rootdir: /Users/ringods/Projects/customer/project/tests/integration,
inifile: pytest-integration.ini
plugins: cov-2.6.0, mamba-1.0.0
collected 629 items
As expected, no trace of the random-order plugin. I pushed my changes to our build server (Jenkins), and this is the output from Jenkins:
+ pytest -c pytest-integration.ini --junitxml=integration-tests.xml tests/integration/
===================== test session starts ========================
platform linux -- Python 3.6.3, pytest-3.7.2, py-1.7.0, pluggy-0.8.0
Test order randomisation NOT enabled. Enable with --random-order or -- random-order-bucket=<bucket_type>
rootdir: /home/centos/workspace/test-reporting-L2CS5UFPVK3I5UNI6BJIMJPWQQMDOV465LKDS2BSKJ5UXDZGAI6Q/tests/integration, inifile: pytest-integration.ini
plugins: random-order-1.0.4, cov-2.6.0, mamba-1.0.0
collected 629 items
I can not seem to find why the random-order plugin is still loaded. Can anyone help me out?
Make sure that config file which you use locally is same as in Jenkins.
Please check if you have pushed changes in config file as well.
Related
After multiple successful tests, pytest is suddenly throwing this error:
$ pytest -vvv -x --internal --oclint -n -32
============================= test session starts ==============================
platform darwin -- Python 3.7.7, pytest-5.4.1, py-1.7.0, pluggy-0.13.1 -- /usr/local/opt/python/bin/python3.7
cachedir: .pytest_cache
rootdir: /Users/pre-commit-hooks/code/pre-commit-hooks, inifile: pytest.ini
plugins: xdist-1.31.0, forked-1.1.3
ERROR: MISSING test execution (tx) nodes: please specify --tx
This is my pytest.ini:
[pytest]
markers =
oclint: marks tests as slow (deselect with '-m "not slow"')
internal: marks tests as checking internal components. Use this if you are developing hooks
-n # is from pytest-xdist, which is an addon to pytest.
This was strange to me because pytest on a travis linux build was working just fine until the last iteration.
Question
Why is pytest asking me to add --tx for my tests?
If you fat-finger a dash after the -n number like -n -32, pytest will complain about a missing --tx option. In other words the number after -n cannot be negative and what you want to use instead is -n 32.
--tx is normally used like so to invoke a Python2.7 subprocess:
pytest -d --tx popen//python=python2.7
More information about using --tx as part of pytest can be found in the pytest-xdist [docs on this flag](pytest -d --tx popen//python=python2.7).
I got this same pytest-xdist error but for a different reason. I had set --forked --dist=loadfile but did not specify --numprocesses. Setting that option fixed the error.
Just FYI: Similar error can happen if one specifies e.g. dist=loadfile without specifying -n 32.
very similar to issue #8222 on the vscode-python github.com issues list, but that thread seemed dead, so I am opening a new one
Environment Data
VSCode install
Version: 1.39.2 (user setup)
Commit: 6ab598523be7a800d7f3eb4d92d7ab9a66069390
Date: 2019-10-15T15:35:18.241Z
Electron: 4.2.10
Chrome: 69.0.3497.128
Node.js: 10.11.0
V8: 6.9.427.31-electron.0
OS: Windows_NT x64 6.1.7601
VSCode Remote - SSH
I am using VSCode Remote - SSH to do all dev and testing on a remote linux system, version 0.48.0
VSCode Extensions
Using only the VSCode Python extension ms-python.python version 2019.11.50794
I used to use the python test extension but that capability is now absorbed into the python extension, which is great
VSCode project settings.json
{
"python.pythonPath": "/local/me/opt/miniconda3/envs/deathstar/bin/python",
"python.testing.pytestArgs": [
"test",
"--disable-warnings",
],
"python.testing.unittestEnabled": false,
"python.testing.nosetestsEnabled": false,
"python.testing.pytestEnabled": true,
}
Python
$ python --version
Python 3.6.8 :: Anaconda, Inc.
$ python -c "import pytest;print(pytest.__version__)"
5.3.1
Expected behavior
VSCode is able to execute the tests as shown in the test discovery.
VSCode adornments show in test .py files
Actual behavior
Test discover works and the tests show in the Test Explorer, great!
Test adornments do not show in the Text Editor window
When running a test, the test file, which was already discovered, cannot be found and the test execution fails out with stack trace in DEBUG CONSOLE
============================= test session starts ==============================
platform linux -- Python 3.6.8, pytest-5.3.1, py-1.8.1, pluggy-0.13.1
rootdir: /home/me/project/project_name
collected 0 items
-------------- generated xml file: /tmp/tmp-304736fTj9ikMPptk.xml --------------
============================== 1 warning in 0.01s ==============================
ERROR: file not found: ./test_mything_plugin.py::test_get_conn
Output
Developer Tools Console
[Extension Host] Info Python Extension: 2019-12-31 20:10:20: Cached data exists ActivatedEnvironmentVariables, /home/tjones/project/airflow_etl
console.ts:137 [Extension Host] Info Python Extension: 2019-12-31 20:10:20: getActivatedEnvironmentVariables, Class name = b, completed in 1ms, Arg 1: <Uri:/home/tjones/project/airflow_etl>, Arg 2: undefined, Arg 3: undefined
console.ts:137 [Extension Host] Info Python Extension: 2019-12-31 20:10:20: > /local/tjones/opt/miniconda3/envs/airflow/bin/python -m pytest --rootdir ~/project/airflow_etl --junitxml=/tmp/tmp-1575s6J3FtN4Ho55.xml --disable-warnings ./test_bam_ctds_plugin.py::test_get_conn
console.ts:137 [Extension Host] Info Python Extension: 2019-12-31 20:10:20: cwd: ~/project/airflow_etl
Python Output
_when I hit the debug button, I get nothing, but when I hit the Play button, I get this
> /local/tjones/opt/miniconda3/envs/airflow/bin/python -m pytest --rootdir ~/project/airflow_etl --junitxml=/tmp/tmp-1575D8SX75zh6k5j.xml --disable-warnings ./test_bam_ctds_plugin.py::test_get_conn
cwd: ~/project/airflow_etl
> /local/tjones/opt/miniconda3/envs/airflow/bin/python -m pytest --rootdir ~/project/airflow_etl --junitxml=/tmp/tmp-1575s6J3FtN4Ho55.xml --disable-warnings ./test_bam_ctds_plugin.py::test_get_conn
cwd: ~/project/airflow_etl
Typically the code lenses for tests fail because either another extension interferes (e.g. gitlens) or the code isn't being picked up by IntelliSense (i.e. Jedi or the Microsoft Python Language Server). I would try turning off your other extensions and see if that solves the problem. I would also check that you get code completion in your tests files.
I want to see stdout coming from a python test inside the jenkins build logs. I'm running pytest (==5.3.1) from within my Jenkins pipeline inside an sh script:
stage('unit tests') {
print "starting unit tests"
sh script: """
source env-test/bin/activate && \
python -m pytest -x -s src/test/test*.py
""", returnStdout: true, returnStatus: true
}
Note that I'm running my tests from with a virtual environment (env-test).
Unfortunately, the Jenkins logs do not display output that I send from within my tests:
def test_it(self):
print('\nhello world')
self.assertTrue(True)
But it only shows the initial call:
+ python -m pytest -x -s src/test/testModel.py
[Pipeline] }
[Pipeline] // stage
Whereas my local pycharm ide and gitbash shows all output:
============================= test session starts =============================
platform win32 -- Python 3.6.4, pytest-5.3.1, py-1.8.0, pluggy-0.13.1 -- C:\...\Anaconda3\python.exe
cachedir: .pytest_cache
rootdir: C:\...\src\test
collecting ... collected 1 item
testModel.py::TestModel::test_it
PASSED [100%]
hello world
============================== 1 passed in 0.57s ==============================
The pytest docs are talking about Capturing of the stdout/stderr output. So I tried to use the -s parameter in order to disable capturing but without success.
The issue was the returnStdout parameter of the groovy sh script command:
returnStdout (optional) If checked, standard output from the task is
returned as the step value as a String, rather than being printed to
the build log. (Standard error, if any, will still be printed to the
log.) You will often want to call .trim() on the result to strip off a
trailing newline. Type: boolean
So I simply remove that option from the sh script command.
I have this Dockerfile that contains a line RUN py.test -vv.
FROM bitnami/python:3.6-prod
#MORE DIRECTIVES
RUN py.test -vv
COPY . /files
WORKDIR /files
EXPOSE 8080
When I run docker-compose build, I am getting this error.
Step 16/21 : RUN py.test -vv
---> Running in 5b3f55f10025
============================= test session starts ==============================
platform linux -- Python 3.6.9, pytest-5.2.1, py-1.8.0, pluggy-0.13.0 -- /opt/bitnami/python/bin/python
cachedir: .pytest_cache
rootdir: /
plugins: ordering-0.6, cov-2.8.1, docker-compose-3.1.2, celery-4.3.0
collecting ... collected 0 items / 1 errors
==================================== ERRORS ====================================
________________________ ERROR collecting test session _________________________
opt/bitnami/python/lib/python3.6/site-packages/_pytest/config/__init__.py:456: in _importconftest
return self._conftestpath2mod[key]
E KeyError: PosixPath('/opt/bitnami/python/lib/python3.6/site-packages/matplotlib/tests/conftest.py')
During handling of the above exception, another exception occurred:
opt/bitnami/python/lib/python3.6/site-packages/_pytest/config/__init__.py:462: in _importconftest
mod = conftestpath.pyimport()
opt/bitnami/python/lib/python3.6/site-packages/py/_path/local.py:701: in pyimport
__import__(modname)
opt/bitnami/python/lib/python3.6/site-packages/matplotlib/tests/__init__.py:16: in <module>
'The baseline image directory does not exist. '
E OSError: The baseline image directory does not exist. This is most likely because the test data is not installed. You may need to install matplotlib from source to get the test data.
During handling of the above exception, another exception occurred:
opt/bitnami/python/lib/python3.6/site-packages/py/_path/common.py:377: in visit
for x in Visitor(fil, rec, ignore, bf, sort).gen(self):
opt/bitnami/python/lib/python3.6/site-packages/py/_path/common.py:429: in gen
for p in self.gen(subdir):
opt/bitnami/python/lib/python3.6/site-packages/py/_path/common.py:429: in gen
for p in self.gen(subdir):
opt/bitnami/python/lib/python3.6/site-packages/py/_path/common.py:429: in gen
for p in self.gen(subdir):
opt/bitnami/python/lib/python3.6/site-packages/py/_path/common.py:429: in gen
for p in self.gen(subdir):
opt/bitnami/python/lib/python3.6/site-packages/py/_path/common.py:429: in gen
for p in self.gen(subdir):
opt/bitnami/python/lib/python3.6/site-packages/py/_path/common.py:429: in gen
for p in self.gen(subdir):
opt/bitnami/python/lib/python3.6/site-packages/py/_path/common.py:429: in gen
for p in self.gen(subdir):
opt/bitnami/python/lib/python3.6/site-packages/py/_path/common.py:418: in gen
dirs = self.optsort([p for p in entries
opt/bitnami/python/lib/python3.6/site-packages/py/_path/common.py:419: in <listcomp>
if p.check(dir=1) and (rec is None or rec(p))])
opt/bitnami/python/lib/python3.6/site-packages/_pytest/main.py:606: in _recurse
ihook = self.gethookproxy(dirpath)
opt/bitnami/python/lib/python3.6/site-packages/_pytest/main.py:424: in gethookproxy
my_conftestmodules = pm._getconftestmodules(fspath)
opt/bitnami/python/lib/python3.6/site-packages/_pytest/config/__init__.py:434: in _getconftestmodules
mod = self._importconftest(conftestpath)
opt/bitnami/python/lib/python3.6/site-packages/_pytest/config/__init__.py:470: in _importconftest
raise ConftestImportFailure(conftestpath, sys.exc_info())
E _pytest.config.ConftestImportFailure: (local('/opt/bitnami/python/lib/python3.6/site-packages/matplotlib/tests/conftest.py'), (<class 'OSError'>, OSError('The baseline image directory does not exist. This is most likely because the test data is not installed. You may need to install matplotlib from source to get the test data.',), <traceback object at 0x7f814caaef88>))
!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!
============================== 1 error in 11.83s ===============================
ERROR: Service 'testproject' failed to build: The command '/bin/sh -c py.test -vv' returned a non-zero code: 2
I have tried adding pip install matplotlib in the Dockerfile but I am still getting the same error.
I have a NodeJS app before that was also Dockerized that has some tests on it using mocha and putting RUN mocha inside the Dockerfile works fine. I'm not sure what's the issue here in Python.
I feel that the issue here is because pytest is not pre-installed in python. Hence you have to add steps for pytest installation in the docker container. Personally I have been running this by using a seperate dockerfile for pytest, which is using for installing and setting the ENTRYPOINT as pytest.
I have attached the docker-compose.yaml, dockerfile and pytest.dockerfile for you reference. Alternatively you can directly mention the pytest installation steps in the .yaml file/dockerfile itself as you are not having any other services to be added and to avoid the additional dockerfile. This set-up is runing perfectly for me for running Selenium-pytest test automation using docker containers. Please try this and let us know the feedback.
version: '3.7'
services:
test:
volumes:
- .:/files
build:
context: .
dockerfile: pytest.dockerfile
docker-compose.yaml
FROM python:3.7-alpine
MAINTAINER xyz
ADD . /files
WORKDIR /files
ENV PYTHONDONTWRITEBYTECODE=true
EXPOSE 4444
dockerfile.
The option to expose the port is again optional here.
FROM python:3.7-alpine
MAINTAINER xyz
RUN pip install pytest
ENTRYPOINT [ "pytest" ]
pytest.dockerfile
I'm writing some integration tests that involve a Python application running under uwsgi.
To test an aspect of this, I am running an uwsgi spooler, which requires that the master process is running.
If pytest has a failed test, it returns a non-zero exit code, which is great.
Without the master process, the entire uwsgi process also returns this exit code, and so our continuous integration server responds appropriately.
However, when the master process is running, it always exits with a zero exit code - regardless of failed tests.
I need it to pass on the first non-zero exit code of a subprocess if there is one.
Note: I'm not really interested in mocking this out - I need to test this working.
I've created a Dockerized Minimal, Complete, and Verifiable Example that illustrates my issue:
Dockerfile:
FROM python:3.6.4-slim-stretch
WORKDIR /srv
RUN apt-get update \
&& apt-get install -y build-essential \
&& pip install uwsgi pytest
COPY test_app.py /srv/
CMD ['/bin/bash']
test_app.py:
import pytest
def test_this():
assert 1==0
Given the above 2 files in a directory, the following shows the return code if I run this failing test under uwsgi without the master process:
$ docker build -t=test .
$ docker run test uwsgi --chdir /srv --pyrun /usr/local/bin/pytest
...
============================= test session starts ==============================
platform linux -- Python 3.6.4, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: /srv, inifile:
collected 1 item
test_app.py F [100%]
=================================== FAILURES ===================================
__________________________________ test_this ___________________________________
def test_this():
> assert 1==0
E assert 1 == 0
test_app.py:4: AssertionError
=========================== 1 failed in 0.05 seconds ===========================
$ echo $?
1
Note: you can see that the return code from this process (last line) is non-zero as required
Now, changing nothing other than running uwsgi with the master process, we get the following output:
$ docker run test uwsgi --set master=true --chdir /srv --pyrun /usr/local/bin/pytest
...
============================= test session starts ==============================
platform linux -- Python 3.6.4, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: /srv, inifile:
collected 1 item
test_app.py F [100%]
=================================== FAILURES ===================================
__________________________________ test_this ___________________________________
def test_this():
> assert 1==0
E assert 1 == 0
test_app.py:4: AssertionError
=========================== 1 failed in 0.05 seconds ===========================
worker 1 buried after 0 seconds
goodbye to uWSGI.
$ echo $?
0
Note: this time the return code from this process (last line) is zero - even though the test failed
How can I get uwsgi to forward the exit code from a failing process to the master?
This works, but feels a little hacky. I'll happily accept a better answer if one comes along.
I've made this work with the addition of two additional files (and a small update to the Dockerfile):
Dockerfile:
FROM python:3.6.4-slim-stretch
WORKDIR /srv
RUN apt-get update \
&& apt-get install -y build-essential \
&& pip install uwsgi pytest
COPY test_app.py test run_tests.py /srv/
CMD ['/bin/bash']
test:
#!/bin/bash
uwsgi --set master=true --chdir /srv --pyrun /srv/run_tests.py
exit $(cat /tmp/test_results)
run_tests.py:
#!/usr/bin/python
import re
import subprocess
import sys
from pytest import main
def write_result(retcode):
path = r'/tmp/test_results'
with open(path, 'w') as f:
f.write(str(retcode))
def run():
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
retcode = 1
try:
retcode = main()
finally:
write_result(retcode)
sys.exit(retcode)
if __name__ == '__main__':
run()
The way it works is that I've copied and tweaked the pytest program into run_tests.py, where it writes out the return code of the tests to a temporary file. The tests are run via a bash script: test, that runs uwsgi, which runs the tests, then exits the script with the return code from the tests.
Results now look like:
$ docker build -t=test .
$ docker run test /srv/test
...
============================= test session starts ==============================
platform linux -- Python 3.6.4, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: /srv, inifile:
collected 1 item
test_app.py F [100%]
=================================== FAILURES ===================================
__________________________________ test_this ___________________________________
def test_this():
> assert 1==0
E assert 1 == 0
test_app.py:4: AssertionError
=========================== 1 failed in 0.05 seconds ===========================
worker 1 buried after 0 seconds
goodbye to uWSGI.
$ echo $?
1