When I create a tox environment, some libraries are installed under different paths depending on the environment that I use to trigger tox:
# Tox triggered inside virtual env
.tox/lib/site-packages
Sometimes
# Tox triggered inside docker
.tox/lib/python3.8/site-packages
I need to reuse such path in further steps inside tox env. I decided to create a bash script to find the path for installed libraries to be able to reuse it and to run it inside tox env. I thought that I can pass found path to tox and reuse it in one of the next commands. Is it possible to do such thing?
I tried:
tox.ini
[tox]
envlist =
docs
min_version = 4
skipsdist = True
allowlist_externals = cd
passenv =
HOMEPATH
PROGRAMDATA
basepython = python3.8
[testenv:docs]
changedir = docs
deps =
-r some_path/library_name/requirements.txt
commands =
my_variable=$(bash ../docs/source/script.sh)
sphinx-apidoc -f -o $my_variable/source $my_variable
But apparently this doesn't work with tox:
docs: commands[0] docs> my_variable=$(bash ../docs/source/script.sh)
docs: exit 2 (0.03 seconds) docs>
my_variable=$(bash../docs/source/script.sh) docs: FAIL code 2
(0.20=setup[0.17]+cmd[0.03] seconds) evaluation failed :( (0.50
seconds)
Bash script
script.sh
#!/bin/bash
tox_env_path="../.tox/docs/"
conf_source="source"
tox_libs=$(find . $tox_env_path -type d -name "<name of library>")
sudo mkdir -p $tox_libs/docs/source
cp $conf_source/conf.py $conf_source/index.rst $tox_libs/docs/source
echo $tox_libs
Not a direct answer to your question, but maybe something like this can help you achieve the actual goal (XY problem):
[testenv:docs]
# ...
allowlist_externals =
bash
commands =
python -c 'print("The path is: {env_site_packages_dir}")'
bash ../docs/source/script.sh
sphinx-apidoc -f -o {env_site_packages_dir}/LibName/source {env_site_packages_dir}/LibName
Indeed, it seems to me like it is unnecessary to compute the path in the bash script and try to read this path in a variable.
1. As far as I know it is not possible to assign values to a variable like you suggest in your question, tox.ini does not allow it.
2. On the other hand, tox.ini allows subsitutions and in particular the {env_site_packages_dir} seems helpful for your use case.
This is my tox.ini file:
# Tox (https://tox.readthedocs.io/) is a tool for running tests
# in multiple virtualenvs. This configuration file will run the
# test suite on all supported python versions. To use it, "pip install tox"
# and then run "tox" from this directory.
#
# See also https://tox.readthedocs.io/en/latest/config.html for more
# configuration options.
[tox]
# Choose your Python versions. They have to be available
# on the system the tests are run on.
# skipsdist=True
ignore_basepython_conflict=false
[testenv:{setup,lint,codestyle,docstyle,tests,doc-linux,doc-darwin,doc-win32}]
basepython=python3.9
envdir = {toxworkdir}/py39
setenv =
PROJECT_NAME = project_name
passenv =
WINDIR
install_command=
pip install \
--find-links=pkg \
--trusted-host=pypi.python.org \
--trusted-host=pypi.org \
--trusted-host=files.pythonhosted.org \
{opts} {packages}
platform = doc-linux: linux
doc-darwin: darwin
doc-win32: win32
deps =
-r{toxinidir}/requirements-dev.txt
-r{toxinidir}/requirements.txt
commands =
setup: python -c "print('All SetUp')"
# Mind the gap, use a backslash :)
lint: pylint -f parseable -r n --disable duplicate-code \
lint: --extension-pkg-whitelist=PyQt5,numpy,torch,cv2,boto3 \
lint: --ignored-modules=PyQt5,numpy,torch,cv2,boto3 \
lint: --ignored-classes=PyQt5,numpy,torch,cv2,boto3 \
lint: project_name \
lint: {toxinidir}/script
lint: pylint -f parseable -r n --disable duplicate-code \
lint: demo/demo_file.py
codestyle: pycodestyle --max-line-length=100 \
codestyle: --exclude=project_name/third_party/* \
codestyle: project_name demo script
docstyle: pydocstyle \
docstyle: --match-dir='^((?!(third_party|deprecated)).)*' \
docstyle: project_name demo script
doc-linux: make -C {toxinidir}/doc html
doc-darwin: make -C {toxinidir}/doc html
doc-win32: {toxinidir}/doc/make.bat html
tests: python -m pytest -v -s --cov-report xml --durations=10 \
tests: --cov=project_name --cov=script \
tests: {toxinidir}/test
tests: coverage report -m --fail-under 100
On tox<4.0 it was very convinient to run tox -e lint to fix linting stuff or tox -e codestyle tox fix codestyle stuff, etc. But now, with version tox>4.0 each time I run one of these commands I get this message (for instance):
codestyle: recreate env because env type changed from {'name': 'lint', 'type': 'VirtualEnvRunner'} to {'name': 'codestyle', 'type': 'VirtualEnvRunner'}
codestyle: remove tox env folder .tox/py39
And it takes forever to run these commands since the evironments are recreated each time ...
I also use these structure for running tests on jenkins so I can map each of these commands to a jenkins stage.
How can I reuse the environment? I have read that it is possible to do it using plugins, but no idea how this can be done, or how to install/use plugins.
I have tried this:
tox multiple tests, re-using tox environment
But it does not work in my case.
I spect to reuse the environment for each of the environments defined in the tox file.
As an addition to N1ngu's excellent answer...
You could re-structure your tox.ini as following:
[tox]
...
[testenv]
<here goes all the common configuration>
[testenv:lint]
<here goes the lint specific configuration>
[testenv:codestyle]
...
And so on. This is a common setup.
While still the environments need to be created at least once, they won't get recreated on each invocation.
This all said, you could also have a look at https://pre-commit.com/ to run your linters, which is very common in the Python community.
Then you would have a tox.ini like the following...
[tox]
...
[testenv]
<here goes all the common configuration>
[testenv:lint]
deps = pre-commit
commands = pre-commit run --all-files
There is now a definite answer about re-use of environments in the faq:
https://tox.wiki/en/latest/upgrading.html#re-use-of-environments
I fear the generative names + factor-specific commands solution you linked relied on tox-3 not auto-recreating the environments by default, which is among the new features in tox 4. Now, environment recreation is something that can be forced (--recreate) but can't be opted-out.
Official answer on this https://github.com/tox-dev/tox/issues/425 boils down to
Officially we don't allow sharing tox environments at the moment [...] As of today, each tox environment has to have it's own virtualenv even if the Python version and dependencies are identical [...] We'll not plan to support this. However, tox 4 allows one to do this via a plugin, so we'd encourage people [...] to try it [...]. Once the project is stable and widely used we can revisit accepting it in core.
So that's it, write a plugin. No idea on how to do that either, so my apologies if this turns out as "not an answer"
This is the path to the project
D:\QA\test-framework\python-client
This is a test frame work implemented by python
This is the python file that contains tests
This is the path to the test case that I need to run
D:\QA\test-framework\python-client\test_data\tests\curve.json
This is the beginning of the curve.json file.
{
"Sklearn - Sklearn - Regression - Curve M2" : [
{
"dataImport": {
"
"
"
]
}
This is the tox.ini file
[tox]
envlist = py38
[testenv]
deps =
pytest
pytest-html
pytest-sugar
pytest-logger
allure-pytest
pytest-xdist
pytest_steps
datetime
oauth2client
gspread
aiclub
commands =
pytest -s -v -k _workflow --html=test_report.html --alluredir=allure-
results/ -n auto --dist=loadfile
allure serve allure-results
pytest {posargs}
I need to run only this curve.json using tox command
I want to specifically run a certain tox section which then auto-decides on the specific platform.
The example code-snippet below works fine if I just ran tox -e ALL. Then the platform condition nicely sects out the correct platform.
However, I want to only adress and run a specific section like for instance something like tox -e other (not tox -e other-win, other-linux) and then have tox auto-chosing the corresponding platform (or any other) condition.
I don't know if this way of setting up conditions in tox is not possible, or if I'm missing something.
[tox]
skipsdist = true
[testenv:systest-{win, linux}]
platform =
linux: linux
win: win|msys
whitelist_externals =
win: cmd
linux: sh
commands =
win: cmd /r echo {env:OS}
linux: sh -c echo {env:OS}
[testenv:other-{win, linux}]
platform =
linux: linux
win: win|msys
whitelist_externals =
win: cmd
linux: sh
commands =
win: cmd /r echo {env:OS}
linux: sh -c echo {env:OS}
You could give the tox-factor plugin a try.
For example:
tox.ini
[tox]
envlist =
alpha-{redmond,tux}
bravo-{redmond,tux}
requires =
tox-factor
skipsdist = true
[testenv]
commands =
python -c 'import sys; print("platform", sys.platform)'
platform =
redmond: win32
tux: linux
This gives the following four environments:
$ tox --listenvs
alpha-redmond
alpha-tux
bravo-redmond
bravo-tux
That can be selected according to the factors:
$ tox --listenvs --factor tux
alpha-tux
bravo-tux
$ tox --listenvs --factor alpha
alpha-redmond
alpha-tux
And then run like this (for example on a Linux platform):
$ tox --factor bravo
bravo-tux run-test-pre: PYTHONHASHSEED='1770792708'
bravo-tux run-test: commands[0] | python -c 'import sys; print("platform", sys.platform)'
platform linux
________________________________________________ summary ________________________________________________
SKIPPED: bravo-redmond: platform mismatch ('linux' does not match 'win32')
bravo-tux: commands succeeded
congratulations :)
References:
https://github.com/tox-dev/tox/issues/1338
https://pypi.org/project/tox-factor/
yml version works (both in CI and locally inputting script commands manually)
staging:
stage: test
image: foobar/python36-qt
script:
- pip install things...
- export PATH=/root/.local/bin:$PATH
- export DISPLAY=":$(( ( RANDOM % 250 ) + 1 ))"
- Xvfb $DISPLAY -screen 0 1920x1080x16 &
- pytest --ignore src/foobar/tests/gui/functional
tox version does not work (I run it locally with python3 -m tox -rc tox.ini -e foobar -v)
[testenv:foobar]
whitelist_externals =
Xvfb
sh
setenv =
PATH={env:PATH}:/root/.local/bin
DISPLAY=":3"
QT_DEBUG_PLUGINS=1
deps =
pytest
install_command = pip install --extra-index-url https://pypi-ext.foobar.com/simple {opts} {packages}
commands =
sh -c 'Xvfb ":3" -screen 0 1920x1080x16 &'
pytest -sv tests --ignore tests/gui/functional
initial error:
foobar run-test: commands[2] | sh -c 'Xvfb ":3" -screen 0 1920x1080x16 &'
[17538] /home/localadmin/Documents/foobar/src/foobar$ /bin/sh -c 'Xvfb ":3" -screen 0 1920x1080x16 &'
foobar run-test: commands[3] | pytest -sv tests --ignore tests/gui/functional
[17540] /home/localadmin/Documents/foobar/src/foobar$ /home/localadmin/Documents/foobar/src/foobar/.tox/foobar/bin/pytest -sv tests --ignore tests/gui/functional
_XSERVTransSocketUNIXCreateListener: ...SocketCreateListener() failed
_XSERVTransMakeAllCOTSServerListeners: server already running
(EE)
Fatal server error:
(EE) Cannot establish any listening sockets - Make sure an X server isn't already running(EE)
resulting error:
qt.qpa.xcb: could not connect to display ":3"
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
The first thing I need to solve is why I constantly get _XSERVTransMakeAllCOTSServerListeners: server already running. Before I select a number X in Display=":X", I check /tmp and /tmp/.X11-unix to make sure no X screen exists, and remove it if it does.
I thought maybe I need to run them in the same command (I figure the [17538] and [17540] are processes (?)). No dice