How to run different tox command inside Jenkins environment? - python

I would like to use different command line arguments for py.test, depending on environment: running locally there should be only default ones, but on Jenkins I would like to add --junitxml=junit-{envname}.xml, so the test results could be published in nice format.
I know from documentation, that there is special [tox:jenkins] section, which should be used in case there is defined 'JENKINS_URL' or 'HUDSON_URL'. So now I created simple tox.ini file:
[tox]
envlist = py27, py35
[tox:jenkins]
commands = echo "We are in JENKINS!"
[testenv]
setenv =
PYTHONPATH = {toxinidir}:{toxinidir}/my_module
commands = python setup.py test
deps =
-r{toxinidir}/requirements.txt
-r{toxinidir}/requirements_test.txt
And have defined JENKINS_URL environment variable:
export JENKINS_URL=true
I expect, that if I run tox, then my original command will be substituted with echo, but it doesn't work, instead I end with original command been executed.
Could someone help me with this problem?

Okay, found the solution myself:
[tox]
envlist = py27, py35
[testenv]
setenv =
PYTHONPATH = {toxinidir}:{toxinidir}/my_module
commands = py.test {env:CUSTOM_ARGS} ; <== use environment variable here
deps =
-r{toxinidir}/requirements.txt
-r{toxinidir}/requirements_test.txt
and in Jenkins just define CUSTOM_ARGS environment variable like this:
export CUSTOM_ARGS="--junitxml=junit.xml"

You could have used positional arguments.
Like this:
commands = py.test --mandatory-flag {posargs:--default-flag}
And in Jenkins you can call tox like this:
tox -- --override-flag
Note the separation with two dashes --.

Related

Setting $PATH via a command with tox

Currently using tox to test a python package, and using a python library (chromedriver-binary) to install chromedriver.
This library creates a script (chromedriver-path) which when called outputs the PATH where chromedriver is installed. The usual way to use this is to run:
export PATH=$PATH:`chromedriver-path`
I've tried the following without success in tox.ini
setenv=
PATH = {env:PATH}{:}`chromedriver-path`
This errors as expected:
FileNotFoundError: [Errno 2] No such file or directory: 'chromedriver': 'chromedriver'
Implying that the setenv command is never called/run.
commands=
export PATH=$PATH:`chromedriver-path
This fails with:
ERROR: InvocationError for command could not find executable export
How do I make this work?
Commands can't change their parent processes' environment variables, and thus can't change the environment variables of subsequent commands launched by forking that parent; they can only set environment variables for themselves or their own children.
If you were able to collect the output of chromedriver-path before starting tox, this would be moot. If it's only available in an environment tox itself creates, then things get a bit more interesting.
One approach you can follow is to wrap the commands that need this path entry in a shim that adds it. Consider changing:
commands=
py test ...
to:
commands=
sh -c 'PATH=$PATH:$(chromedrive-path); exec "$#"' _ py test ...

Get path of virtual environment in pipenv

How to can get the path of virtualenv in pipenv?
can configure it to use a custom path for newly created virtualenv?
The following should give you the paths
$ pipenv --where
/home/wonder/workspace/myproj
$ pipenv --venv
/home/wonder/PyEnvs/myproj-BKbQCeJj
Adding to Sewagodimo Matlapeng's answer for the second part of the question:
can configure it to use a custom path for newly created virtualenv?
According to documentation, you can set the base location for the virtualenvs with the environment variable WORKON_HOME. If you want to place the virtualenv specifically in <project>/.venv, set the environment variable PIPENV_VENV_IN_PROJECT.
e.g., running:
export WORKON_HOME=/tmp
pipenv install
Would place the virtualenv in /tmp/<projectname>-<hash>.
I create a command to handle this:
https://github.com/tw-yshuang/Ubuntu-Setup-Scripts/blob/8917578f9ad95be03f48608b7068337215d33f92/config/.customfunction#L12
From line 12 ~ 105
Usage: pipenv_correspond [OPTION]
OPTION:
ls, --list list all the corresponding projects_root & venvs
uls, --useless list all the not existing projects_roots that still have corresponding venvs
npr, --no-project-root hide projects_root
rm, --remove remove all the venvs from command: "ls" or "uls", deafult is use "uls"
# example
$ pipenv_correspond ls
There have some options that suggest you enable this command:
Recommend, create a ~/.customfunction file and
paste it, then use this command:
$ echo '# customfunction\nsource ~/.customfunction' >> <shell_profile>
shell_profile, e.g. ~/.bash_profile, ~/.zshrc
you can copy this code from line 12 ~ 105 to your shell_profile.
You can simple use following command:
pipenv --where

Platform specific settings in tox

I would like to specify a few additional settings in my tox configuration, but only when I'm running on a certain platform.
For example, when running on windows I want an extra environment variable to be defined. I would like to do something like this
[tox]
envlist = env1, env2, env_win32, env_arch
[testenv]
commands=
do stuff...
[testenv]
platform = arch
setenv =
NAME = VALUE
[testenv:env_win32]
plaform = win32
more = stuff
[testenv:env_arch]
platform = arch
more = different_stuff
but this doesn't work because of the duplicate testenv section. I want the specified environment variable to apply to all environments (e.g. env1, env2, env_arch) but not on env_win32.
Note: The specific case that I'm dealing with is that on *nix platforms we need to specify an extra environment variable for install_command only, so the command includes /usr/bin/env NAME=VALUE at the beginning. Unfortunately, this doesn't exist on windows which causes it to fail. I want to conditionally define the install_command differently depending on the platform to get around this.
[tox]
envlist = env1, env2, env_win32, env_linux
[testenv]
install_command = pip install {opts} {packages}
[testenv-linux]
platform = linux
install_command = /usr/bin/env NAME=VALUE pip install {opts} {packages}
[testenv:env_win32]
plaform = win32
install_command = {[testenv]install_command}
[testenv:env_linux]
platform = linux
install_command = {[testenv-linux]install_command}

how to configure tox for getting the logs

I am trying to use tox automating testing in my project. But I am not able to figure out where the logs or prints from my test_methods in python file goes while using tox. I also grepped the entire tox directory for logs but couldn't find it.
Questions
1) How to configure log directory in tox ?
2) What is the default configuration for logs ?
Any Pointers to the documentation and examples ?
My tox.ini file
[tox]
minversion = 1.6
skipsdist = True
[testenv]
skip_install = True
setenv =
VIRTUAL_ENV={envdir}
deps = -r{toxinidir}/test-requirements.txt
passenv = LANG
[testenv:test]
commands = ./test.sh --slowest --testr-args='{posargs}'
it's not really an answer, but I ended up using asserts.. so instead of
print(type(x))
I do
assert type(x)==1
which gives me
E AssertionError: assert <class 'tuple'> == 1
... so it's a tuple.. A bit crap but it works
There's envlogdir exactly for that:
envlogdir=path
defines a directory for logging where tox will put logs of tool invocation.
default: {envdir}/log
By default your testrunner's logs are in ./.tox/envname/log/envname-k.log where envname is environment name (e.g. py27) and k is number of the command which actually runs your testrunner (python -m testtools.run). k==0 is envname creation log, k==1 is log for first dependency installation, etc.
You can use --verbose and throw error intentionaly to print out log
Example:
print('HERE')
assertTrue(False)
tox -e unit-tests --verbose
If you use Linux, you can simply log the test using:
tox > toxlog.txt
And the output will be in the toxlog.txt file

Python and environment variables

In the following code snippet (meant to work in an init.d environment) I would like to execute test.ClassPath. However, I'm having trouble setting and passing the CLASSPATH environment variable as defined in the user's .bashrc.
Here is the source of my frustration:
When the below script is run in use mode, it prints out the CLASSPATH OK (from $HOME/.bashrc)
when I run it as root, it also displays CLASSPATH fine (I've set up /etc/bash.bashrc with CLASSPATH)
BUT when I do "sudo script.py" (to simulate what happens at init.d startup time), the CLASSPATH is missing !!
The CLASSPATH is quite large, so I'd like to read it from a file .. say $HOME/.classpath
#!/usr/bin/python
import subprocess
import os.path as osp
import os
user = "USERNAME"
logDir = "/home/USERNAME/temp/"
print os.environ["HOME"]
if "CLASSPATH" in os.environ:
print os.environ["CLASSPATH"]
else:
print "Missing CLASSPATH"
procLog = open(osp.join(logDir, 'test.log'), 'w')
cmdStr = 'sudo -u %s -i java test.ClassPath'%(user, ) # run in user
proc = subprocess.Popen(cmdStr, shell=True, bufsize=0, stderr=procLog, stdout=procLog)
procLog.close()
sudo will not pass environment variables by default. From the man page:
By default, the env_reset option is enabled. This causes
commands to be executed with a minimal environment containing
TERM, PATH, HOME, MAIL, SHELL, LOGNAME, USER and USERNAME in
addition to variables from the invoking process permitted by
the env_check and env_keep options. This is effectively a
whitelist for environment variables.
There are a few ways of addressing this.
You can edit /etc/sudoers to explicitly pass the CLASSPATH
variable using the env_keep configuration directive. That might
look something like:
Defaults env_keep += "CLASSPATH"
You can run your command using the env command, which lets you set the environment explicitly. A typical command line invocation might look like this:
sudo env CLASSPATH=/path1:/path2 java test.ClassPath
The obvious advantage to option (2) is that it doesn't require mucking about with the sudoers configuration.
You could put source ~/.bashrc before starting your python script to get the environment variables set.

Categories