CleanCut / green

Green is a clean, colorful, fast python test runner.
MIT License
791 stars 75 forks source link

coverage.py `pragma: no cover` not working #133

Closed lsh-0 closed 7 years ago

lsh-0 commented 7 years ago

coverage.py has a means of excluding lines from coverage: http://coverage.readthedocs.io/en/coverage-4.0.3/excluding.html

I'm uncertain how coverage is being called within green, but these comments are not causing the line to be ignored.

CleanCut commented 7 years ago

Works great for me. Do you have some example code you can provide where it doesn't work? Green makes extensive use of that pragma itself:

$ grep -r pragma green
green/cmdline.py:try: # pragma: no cover
green/cmdline.py:except: # pragma: no cover
green/cmdline.py:    else: # pragma: no cover
green/cmdline.py:if __name__ == '__main__': # pragma: no cover
green/config.py:from __future__ import unicode_literals # pragma: no cover
green/config.py:from __future__ import print_function   # pragma: no cover
green/config.py:import argparse             # pragma: no cover
green/config.py:try:                        # pragma: no cover
green/config.py:except:                     # pragma: no cover
green/config.py:try:                        # pragma: no cover
green/config.py:except:                     # pragma: no cover
green/config.py:import copy                 # pragma: no cover
green/config.py:import logging              # pragma: no cover
green/config.py:import os                   # pragma: no cover
green/config.py:import sys                  # pragma: no cover
green/config.py:import tempfile             # pragma: no cover
green/config.py:from textwrap import dedent # pragma: no cover
green/config.py:import multiprocessing      # pragma: no cover
green/config.py:files_loaded = [] # pragma: no cover
green/config.py:default_args             = argparse.Namespace( # pragma: no cover
green/config.py:class StoreOpt(): # pragma: no cover
green/config.py:def parseArguments(): # pragma: no cover
green/config.py:class ConfigFile(object): # pragma: no cover
green/config.py:def getConfig(filepath=None): # pragma: no cover
green/config.py:def mergeConfig(args, testing=False): # pragma: no cover
green/config.py:    if new_args.help: # pragma: no cover
green/djangorunner.py:    if django.VERSION[:2] < (1, 6): # pragma: no cover
green/djangorunner.py:except ImportError: # pragma: no cover
green/loader.py:            pass # pragma: no cover
green/loader.py:                if test.__class__.__name__ == '_FailedTest': # pragma: no cover
green/loader.py:            except UnicodeDecodeError: # pragma: no cover
green/output.py:if sys.version_info[0] == 3: # pragma: no cover
green/output.py:else: # pragma: no cover
green/output.py:        if platform.system() == 'Windows': # pragma: no cover
green/output.py:                    and not disable_windows)): # pragma: no cover
green/output.py:            if platform.python_version_tuple()[0] == '2': # pragma: no cover
green/output.py:            if self.on_appveyor: # pragma: no cover
green/process.py:try: # pragma: no cover
green/process.py:except: # pragma: no cover
green/process.py:def ddebug(msg, err=None): # pragma: no cover
green/process.py:if platform.python_version_tuple()[0] == '2': # pragma: no cover
green/process.py:else: # pragma: no cover
green/process.py:        wrap_exception=False, finalizer=None, finalargs=()): # pragma: no cover
green/process.py:class RemoteTraceback(Exception): # pragma: no cover
green/process.py:class ExceptionWithTraceback: # pragma: no cover
green/process.py:def rebuild_exc(exc, tb): # pragma: no cover
green/process.py:def poolRunner(target, queue, coverage_number=None, omit_patterns=[]): # pragma: no cover
green/result.py:    def __repr__(self): # pragma: no cover
green/runner.py:try: # pragma: no cover
green/runner.py:except: # pragma: no cover
green/runner.py:        if args.warnings: # pragma: no cover
green/suite.py:except: # pragma: no cover
green/terminal.py:def getTerminalSize(): # pragma: no cover
green/terminal.py:def _getTerminalSizeWindows(): # pragma: no cover
green/terminal.py:def _getTerminalSizeTput(): # pragma: no cover
green/terminal.py:def _getTerminalSizeLinux(): # pragma: no cover
green/test/test_loader.py:        if platform.system() == 'Windows': # pragma: no cover
green/test/test_output.py:        if sys.version_info[0] == 3: # pragma: no cover
green/test/test_output.py:        else: # pragma: no cover
green/version.py:from __future__ import unicode_literals # pragma: no cover
green/version.py:import os.path # pragma nocover
green/version.py:import sys # pragma nocover
green/version.py:try: # pragma nocover
green/version.py:except: # pragma nocover
green/version.py:__version__ = open(os.path.join(os.path.dirname(__file__), 'VERSION')).read().strip() # pragma nocover
green/version.py:if sys.version_info[0] == 2: # pragma nocover
green/version.py:def pretty_version(): # pragma nocover
lsh-0 commented 7 years ago

I have this line here that isn't getting covered and keeping me at 97% coverage: https://github.com/elifesciences/bot-lax-adaptor/blob/develop/src/main.py#L156

covered

if it does actually work then perhaps I'm using it incorrectly.

CleanCut commented 7 years ago

Hmm. It looks like it ought to work just fine.

What is the output of green --version on the box you are running your coverage? And what OS is it?

lsh-0 commented 7 years ago
(venv) [luke@scareme bot-lax-adaptor]$ green --version
Green 2.5.0, Coverage 4.1, Python 2.7.12
(venv) [luke@scareme bot-lax-adaptor]$ pip install green --upgrade
Collecting green
...
Installing collected packages: green
  Found existing installation: green 2.5.0
    Uninstalling green-2.5.0:
      Successfully uninstalled green-2.5.0
Successfully installed green-2.5.1
(venv) [luke@scareme bot-lax-adaptor]$ export PYTHONPATH='src'
(venv) [luke@scareme bot-lax-adaptor]$ green src/ --run-coverage
.....

Name              Stmts   Miss Branch BrPart  Cover
---------------------------------------------------
src/__init__.py       0      0      0      0   100%
src/main.py          57      1      6      1    97%
---------------------------------------------------
TOTAL                57      1      6      1    97%

Ran 5 tests in 1.514s

OK (passes=5)

(edit: I was within the virtualenv the whole time)

CleanCut commented 7 years ago

I get this in both the master and develop branches:

Traceback (most recent call last):
  File "/Users/nathan/tmp/bot-lax-adaptor/venv/bin/green", line 11, in <module>
    sys.exit(main())
  File "/Users/nathan/tmp/bot-lax-adaptor/venv/lib/python2.7/site-packages/green/cmdline.py", line 75, in main
    result = run(test_suite, stream, args, testing)
  File "/Users/nathan/tmp/bot-lax-adaptor/venv/lib/python2.7/site-packages/green/runner.py", line 92, in run
    targets = [(target, manager.Queue()) for target in toParallelTargets(suite, args.targets)]
  File "/Users/nathan/tmp/bot-lax-adaptor/venv/lib/python2.7/site-packages/green/loader.py", line 60, in toParallelTargets
    proto_test_list = toProtoTestList(suite)
  File "/Users/nathan/tmp/bot-lax-adaptor/venv/lib/python2.7/site-packages/green/loader.py", line 45, in toProtoTestList
    toProtoTestList(i, test_list, doing_completions)
  File "/Users/nathan/tmp/bot-lax-adaptor/venv/lib/python2.7/site-packages/green/loader.py", line 45, in toProtoTestList
    toProtoTestList(i, test_list, doing_completions)
  File "/Users/nathan/tmp/bot-lax-adaptor/venv/lib/python2.7/site-packages/green/loader.py", line 45, in toProtoTestList
    toProtoTestList(i, test_list, doing_completions)
  File "/Users/nathan/tmp/bot-lax-adaptor/venv/lib/python2.7/site-packages/green/loader.py", line 45, in toProtoTestList
    toProtoTestList(i, test_list, doing_completions)
  File "/Users/nathan/tmp/bot-lax-adaptor/venv/lib/python2.7/site-packages/green/loader.py", line 37, in toProtoTestList
    getattr(suite, exception_method)()
  File "/Users/nathan/tmp/bot-lax-adaptor/venv/lib/python2.7/site-packages/green/loader.py", line 235, in testFailure
    raise ImportError(message)
ImportError: Failed to import src.tests.tests computed from filename /Users/nathan/tmp/bot-lax-adaptor/src/tests/tests.py
Traceback (most recent call last):
  File "/Users/nathan/tmp/bot-lax-adaptor/venv/lib/python2.7/site-packages/green/loader.py", line 212, in loadFromModuleFilename
    __import__(dotted_module)
  File "/Users/nathan/tmp/bot-lax-adaptor/src/tests/tests.py", line 5, in <module>
    import main
ImportError: No module named main
lsh-0 commented 7 years ago

may I ask the command you are using to invoke green? there is a test.sh script that should be used.

CleanCut commented 7 years ago

Sorry for the huge delay.

I tried on your develop branch today, and I can't get to the point where green would be used.

I made this change locally:

diff --git a/test.sh b/test.sh
index aa824c7..ff3edcf 100755
--- a/test.sh
+++ b/test.sh
@@ -1,11 +1,12 @@
 #!/bin/bash

+set -x
 set -e # everything must pass

 export PYTHONPATH="src"

 # ensure the venv is installed
-. ./install.sh &> /dev/null
+. ./install.sh

 # activate venv
 . ./venv/bin/activate

And then I run ./test.sh and get this (On OS X)

$ ./test.sh
+ set -e
+ export PYTHONPATH=src
+ PYTHONPATH=src
+ . ./install.sh
++ set -e
++ '[' '!' -d venv ']'
++ source venv/bin/activate
+++ deactivate nondestructive
+++ unset -f pydoc
+++ '[' -z '' ']'
+++ '[' -z '' ']'
+++ '[' -n /bin/bash ']'
+++ hash -r
+++ '[' -z '' ']'
+++ unset VIRTUAL_ENV
+++ '[' '!' nondestructive = nondestructive ']'
+++ VIRTUAL_ENV=/Users/nathan/proj/green/bot-lax-adaptor/venv
+++ export VIRTUAL_ENV
+++ _OLD_VIRTUAL_PATH='/Library/Frameworks/Python.framework/Versions/3.4/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/local/sbin:/Users/nathan/Dropbox/bin:/Users/nathan/bin:/Applications/Sublime Text.app/Contents/SharedSupport/bin:/usr/pgsql-9.3/bin:/Users/nathan/NVPACK/android-sdk-macosx/platform-tools:/Library/Frameworks/Python.framework/Versions/3.4/bin'
+++ PATH='/Users/nathan/proj/green/bot-lax-adaptor/venv/bin:/Library/Frameworks/Python.framework/Versions/3.4/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/local/sbin:/Users/nathan/Dropbox/bin:/Users/nathan/bin:/Applications/Sublime Text.app/Contents/SharedSupport/bin:/usr/pgsql-9.3/bin:/Users/nathan/NVPACK/android-sdk-macosx/platform-tools:/Library/Frameworks/Python.framework/Versions/3.4/bin'
+++ export PATH
+++ '[' -z '' ']'
+++ '[' -z '' ']'
+++ _OLD_VIRTUAL_PS1=
+++ '[' x '!=' x ']'
++++ basename /Users/nathan/proj/green/bot-lax-adaptor/venv
+++ PS1='(venv) '
+++ export PS1
+++ alias pydoc
+++ '[' -n /bin/bash ']'
+++ hash -r
++ pip install -r requirements.txt
Collecting coverage==4.1 (from -r requirements.txt (line 1))
  Using cached coverage-4.1-cp27-cp27m-macosx_10_10_x86_64.whl
Collecting et3==1.1 (from -r requirements.txt (line 2))
  Downloading et3-1.1.tar.gz
Collecting elifetools from git+https://github.com/gnott/elife-tools.git@feature-body-back#egg=elifetools (from -r requirements.txt (line 4))
  Cloning https://github.com/gnott/elife-tools.git (to feature-body-back) to /private/var/folders/lp/143b5f2h8xlcqw006s6rfk0r0000gq/T/pip-build-1rQ9UW/elifetools
  Could not find a tag or branch 'feature-body-back', assuming commit.
error: pathspec 'feature-body-back' did not match any file(s) known to git.
Command "git checkout -q feature-body-back" failed with error code 1 in /private/var/folders/lp/143b5f2h8xlcqw006s6rfk0r0000gq/T/pip-build-1rQ9UW/elifetools
lsh-0 commented 7 years ago

yes, unfortunately that project is unstable at the moment and you shouldn't need to install it to replicate it. so, if you can't replicate it, you can't replicate it. I have workarounds for now. Thanks for your attention.

axc450 commented 5 years ago

Sorry to comment on an extremely old issue, but I am facing this problem and seeing as this is the only thing on the internet I can find about this, I thought it might be helpful to leave a (maybe the) solution:

This was not working for me because I had defined a .coveragerc file with exclude_lines. If you have done this, you will have to add the below to the exclude_lines section:

# Dont test lines with this comment
pragma: no cover
CleanCut commented 5 years ago

@axc450 Thanks for that info!

sbellem commented 5 years ago

Thanks @axc450! Also had the same problem.

It is worth noting that the documentation of coverage.py does mention (under https://coverage.readthedocs.io/en/coverage-4.3.4/excluding.html#advanced-exclusion):

Note that when using the exclude_lines option in a configuration file, you are taking control of the entire list of regexes, so you need to re-specify the default “pragma: no cover” match if you still want it to apply.