py.test use -m AS WELL as directory path in command - python

I'd like to only run selenium tests in my test suite, in addition to filtering it down to only run tests in a specific file/folder. It seems like I should be able to accomplish this with the -m option, and the path positional argument. Furthermore, I'm doing this in a bash script.
So for example, I tried something like this:
#!/bin/bash
# ...some logic here for determining `EXTRA` arg
EXTRA = "not selenium"
py.test -m $EXTRA -v -s --tb=long --no-flaky-report ~/project/mytests/test_blerg.py
And then my test looks like this (still using xunit-style classes):
#pytest.mark.selenium
class BaseTest(UnitTest):
pass
class ChildTest(BaseTest):
def test_first_case(self):
pass
When I run the py.test command as I described above, I get this:
============================================================================ no tests ran in 0.01 seconds ============================================================================
ERROR: file not found: selenium"
Not completely sure why this doesn't work. I'll try manually overriding pytest_runtest_setup(), but I'm feel like I should be able to accomplish what I want without doing that. Also, just FYI, this is a django project, using Django==1.8.7 and pytest-django==2.9.1.
Any help would be greatly appreciated :)

Figured it out. This has nothing to do with py.test itself. I had an error in how I was calling the py.test command in my bash script. The amended command looks like this:
py.test -m "$EXTRA" -v -s --tb=long --no-flaky-report ~/project/mytests/test_blerg.py
Works as expected!

Related

get pytest exit code from shell script

I'm running pytest test from shell script.
The relevant line in the script looks something like:
pytest pytest_tests --param=$my_param
According to pytest documentation, "Running pytest can result in six different exit codes" (0-5).
My question is how can I get this exit code from the script?
I tried something like
exit_code = pytest pytest_tests --param=$my_param
echo $exit_code
But I got this:
exit_code: command not found
How can I get it? Or is there a better way to get pytest results in the shell script?
After a command runs its exit code should be available via the $? variable. Try something like this:
pytest pytest_tests --param=$my_param
echo Pytest exited $?
This works in Bash, and should work in the regular sh Bourne shell and zsh as well.
If you need to assign this to another variable, use
my_var=$?
Note the lack of spaces.

How to generate test report using pytest?

How can I generate test report using pytest? I searched for it but whatever i got was about coverage report.
I tried with this command:
py.test sanity_tests.py --cov=C:\Test\pytest --cov-report=xml
But as parameters represents it generates coverage report not test report.
Ripped from the comments: you can use the --junitxml argument.
$ py.test sample_tests.py --junitxml=C:\path\to\out_report.xml
You can use a pytest plugin 'pytest-html' for generating html reports which can be forwarded to different teams as well
First install the plugin:
$ pip install pytest-html
Second, just run your tests with this command:
$ pytest --html=report.html
You can also make use of the hooks provided by the plugin in your code.
import pytest
from py.xml import html
def pytest_html_report_title(report)
report.title = "My very own title!"
Reference: https://pypi.org/project/pytest-html/
I haven't tried it yet but you can try referring to https://github.com/pytest-dev/pytest-html. A python library that can generate HTML output.
py.test --html=Report.html
Here you can specify your python file as well. In this case, when there is no file specified it picks up all the files with a name like 'test_%' present in the directory where the command is run and executes them and generates a report with the name Report.html
You can also modify the name of the report accordingly.

Error in check_call() subprocess, executing 'mv' unix command: "Syntax error: '(' unexpected"

I'm making a python script for Travis CI.
.travis.yml
...
script:
- support/travis-build.py
...
The python file travis-build.py is something like this:
#!/usr/bin/env python
from subprocess import check_call
...
check_call(r"mv !(my_project|cmake-3.0.2-Darwin64-universal) ./my_project/final_folder", shell=True)
...
When Travis building achieves that line, I'm getting an error:
/bin/sh: 1: Syntax error: "(" unexpected
I just tried a lot of different forms to write it, but I get the same result. Any idea?
Thanks in advance!
Edit
My current directory layout:
- my_project/final_folder/
- cmake-3.0.2-Darwin64-universal/
- fileA
- fileB
- fileC
I'm trying with this command to move all the current files fileA, fileB and fileC, excluding my_project and cmake-3.0.2-Darwin64-universal folders into ./my_project/final_folder. If I execute this command on Linux shell, I get my aim but not through check_call() command.
Note: I can't move the files one by one, because there are many others
I don't know which shell Travis are using by default because I don't specify it, I only know that if I write the command in my .travis.yml:
.travis.yml
...
script:
# Here is the previous Travis code
- mv !(my_project|cmake-3.0.2-Darwin64-universal) ./my_project/final_folder
...
It works. But If I use the script, it fails.
I found this command from the following issue:
How to use 'mv' command to move files except those in a specific directory?
You're using the bash feature extglob, to try to exclude the files that you're specifying. You'll need to enable it in order to have it exclude the two entries you're specifying.
The python subprocess module explicitly uses /bin/sh when you use shell=True, which doesn't enable the use of bash features like this by default (it's a compliance thing to make it more like original sh).
If you want to get bash to interpret the command; you have to pass it to bash explicitly, for example using:
subprocess.check_call(["bash", "-O", "extglob", "-c", "mv !(my_project|cmake-3.0.2-Darwin64-universal) ./my_project/final_folder"])
I would not choose to do the job in this manner, though.
Let me try again: in which shell do you expect your syntax !(...) to work? Is it bash? Is it ksh? I have never used it, and a quick search for a corresponding bash feature led nowhere. I suspect your syntax is just wrong, which is what the error message is telling you. In that case, your problem is entirely independent form python and the subprocess module.
If a special shell you have on your system supports this syntax, you need to make sure that Python is using the same shell when invoking your command. It tells you which shell it has been using: /bin/sh. This is usually just a link to the real shell executable. Does it point to the same shell you have tested your command in?
Edit: the SO solution you referenced contains the solution in the comments:
Tip: Note however that using this pattern relies on extglob. You can
enable it using shopt -s extglob (If you want extended globs to be
turned on by default you can add shopt -s extglob to .bashrc)
Just to demonstrate that different shells might deal with your syntax in different ways, first using bash:
$ !(uname)
-bash: !: event not found
And then, using /bin/dash:
$ !(uname)
Linux
The argument to a subprocess.something method must be a list of command line arguments. Use e.g. shlex.split() to make the string be split into correct command line arguments:
import shlex, subprocess
subprocess.check_call( shlex.split("mv !(...)") )
EDIT:
So, the goal is to move files/directories, with the exemption of some file(s)/directory(ies). By playing around with bash, I could get it to work like this:
mv `ls | grep -v -e '\(exclusion1\|exclusion2\)'` my_project
So in your situation that would be:
mv `ls | grep -v -e '\(myproject\|cmake-3.0.2-Darwin64-universal\)'` my_project
This could go into the subprocess.check_call(..., shell=True) and it should do what you expect it to do.

python nose xunit report file is empty

I have a problem running nose tests and get results inside Jenkins.
The job has a shell script like this:
. /var/lib/jenkins/envs/itravel/bin/activate
python api/manage.py syncdb --noinput
DJANGO_SETTINGS_MODULE=ci_settings nosetests --verbosity=0 --processes=1 --with-xunit --xunit-file=nosetests.xml
deactivate
Part of the test suite is run using the django_nose.NoseTestSuiteRunner.
All the tests are run and the resulting nosetests.xml file is created but does not seem to be filled with the tests results:
<?xml version="1.0" encoding="UTF-8"?><testsuite name="nosetests" tests="0" errors="0" failures="0" skip="0"></testsuite>
I noticed that on an import Error fail the file is filled with one error, but otherwise, nothing...
Any idea? Is there something special to do from the tests side? Any property to set or so?
Thanks.
As far as I know, the --processes option is not compatible with --with-xunit. When you ask nosetests to run with the processes plugin, the tests are run in specified number of subprocesses. The xunit plugin does not know how to gather results into the xml file.
Just remove the --processes option and you should be fine.
Nose has had an open and unresolved GitHub issue for this since 2011. As #sti said, everything works fine if you don't use --processes. For everyone else, consider using Ignas/nose_xunitmp instead:
pip install nose_xunitmp
nosetests --with-xunitmp
nosetests --xunitmp-file results.xml

nosetests is capturing the output of my print statements. How to circumvent this?

When I type
$ nosetests -v mytest.py
all my print outputs are captured when all tests pass.
I want to see print outputs even everything passes.
So what I'm doing is to force an assertion error to see the output, like this.
class MyTest(TestCase):
def setUp(self):
self.debug = False
def test_0(self):
a = .... # construct an instance of something
# ... some tests statements
print a.dump()
if self.debug:
eq_(0,1)
It feels so hackish, there must be a better way. Enlighten me please.
Either:
$ nosetests --nocapture mytest.py
Or:
$ NOSE_NOCAPTURE=1 nosetests mytests.py
(it can also be specified in the nose.cfg file, see nosetests --help)
Use
--nologcapture
it worked for me
This was added recently to nose instead of --nocapture do this:
nosetests -s
In order to integrate with http://travis-ci.org I have put this into .travis.yml:
script: "python setup.py nosetests -s"
where setup.py contains:
setup(
...
tests_require=['nose>=1.0'],
test_suite='nose.collector',
)
Try this,
nosetests -v 2 -s yourtest
Flags expect order.

Categories