Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added more tests and coverage process through coveralls #6

Merged
merged 3 commits into from
Apr 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,4 @@ ENV/

.idea
/.project
.pytest_cache
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
language: python
python:
- '3.6'
install: pip install tox

install: pip install tox coveralls
script: tox
after_success: coveralls

deploy:
provider: pypi
on:
Expand Down
9 changes: 6 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
ipdbugger
---------
.. image:: https://travis-ci.org/gregoil/ipdbugger.svg?branch=master
:target: https://travis-ci.org/gregoil/ipdbugger

.. image:: https://img.shields.io/pypi/v/ipdbugger.svg
:alt: PyPI
:target: https://pypi.python.org/pypi/ipdbugger/
Expand All @@ -11,6 +8,12 @@ ipdbugger
:alt: Python versions
:target: https://pypi.python.org/pypi/ipdbugger/

.. image:: https://travis-ci.org/gregoil/ipdbugger.svg?branch=master
:target: https://travis-ci.org/gregoil/ipdbugger

.. image:: https://coveralls.io/repos/github/gregoil/ipdbugger/badge.svg?branch=master
:target: https://coveralls.io/github/gregoil/ipdbugger

``ipdbugger`` is a code debugging tool based on ``ipdb``.

Use the ``debug`` decorator on functions or classes to debug them.
Expand Down
19 changes: 6 additions & 13 deletions ipdbugger/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@


class IPDBugger(Pdb):
"""Deubbger class, adds functionality to the normal pdb."""
"""Debugger class, adds functionality to the normal pdb."""
def do_raise(self, arg):
"""Raise the last exception caught."""
self.do_continue(arg)
Expand Down Expand Up @@ -93,15 +93,8 @@ def start_debugging():


class ErrorsCatchTransformer(ast.NodeTransformer):
"""Surround each statement with a try/except block to catch errors.

Attributes:
IGNORED_EXCEPTION (str): name of the base class of the exceptions
to catch, or None to catch all.
"""
"""Surround each statement with a try/except block to catch errors."""
def __init__(self, ignore_exceptions=(), catch_exception=None):
raise_cmd = ast.Raise()

if sys.version_info > (3, 0):
start_debug_cmd = ast.Expr(
value=ast.Call(
Expand Down Expand Up @@ -133,7 +126,7 @@ def __init__(self, ignore_exceptions=(), catch_exception=None):
0,
ast.ExceptHandler(type=ignore_exception_node,
name=None,
body=[raise_cmd]))
body=[ast.Raise()]))

def generic_visit(self, node):
"""Surround node statement with a try/except block to catch errors.
Expand Down Expand Up @@ -283,6 +276,6 @@ def wrapper(*args, **kw):
return victim

else:
raise RuntimeError("Debugger can only wrap functions and classes")

return victim
raise TypeError(
"Debugger can only wrap functions and classes. "
"Got object {!r} of type {}".format(victim, type(victim).__name__))
10 changes: 8 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
-e .
astroid==1.5.3
attrs==17.4.0
backports.functools-lru-cache==1.4
backports.shutil-get-terminal-size==1.0.0
colorama==0.3.9
configparser==3.5.0
coverage==4.5.1
decorator==4.1.2
enum34==1.1.6
flake8==3.4.1
funcsigs==1.0.2
ipdb==0.10.3
ipython==5.5.0
ipython-genutils==0.2.0
isort==4.2.15
lazy-object-proxy==1.3.1
mccabe==0.6.1
mock==2.0.0
more-itertools==4.1.0
pathlib2==2.3.0
pbr==4.0.2
pexpect==4.2.1
pickleshare==0.7.4
pluggy==0.5.2
prompt-toolkit==1.0.15
ptyprocess==0.5.2
py==1.4.34
py==1.5.3
pycodestyle==2.3.1
pyflakes==1.5.0
Pygments==2.2.0
pylint==1.7.2
pytest==3.5.0
pytest-cov==2.5.1
scandir==1.5
simplegeneric==0.8.1
singledispatch==3.4.0.3
Expand Down
135 changes: 115 additions & 20 deletions tests/unit/test_debug.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,138 @@
"""Unit tests for the debug decorator in ipdbugger module."""
from __future__ import absolute_import
import sys
from unittest import TestCase, main

from IPython.utils.capture import capture_output
import pytest

from ipdbugger import debug


try:
from unittest.mock import patch

except ImportError:
from mock import patch


class DebugCatchesExpcetionsCase(TestCase):
"""Tests that an exception is caught iff one is raised."""
def test_debugging_raising_function():
"""Test debugging a raising function."""
@debug
def should_raise():
raise Exception()

with capture_output(), patch('bdb.Bdb.set_trace') as set_trace:
should_raise()
assert set_trace.called


def test_debugging_raising_method():
"""Test debugging a raising bounded-method."""
class A(object):
def should_raise(self):
raise Exception()

a = A()
a.should_raise = debug(a.should_raise)

with capture_output(), patch('bdb.Bdb.set_trace') as set_trace:
a.should_raise()
assert set_trace.called


def test_debugging_function_twice():
"""Test applying `debug` on a function more than once can be done."""
@debug
@debug
def shouldnt_raise(self):
def should_raise():
raise Exception()

with capture_output(), patch('bdb.Bdb.set_trace') as set_trace:
should_raise()
assert set_trace.called_once


def test_debugging_non_raising_function():
"""Test debugging on a non-raising function."""
@debug
def non_raising_function():
pass

with capture_output(), patch('bdb.Bdb.set_trace') as set_trace:
non_raising_function()
assert not set_trace.called


def test_debugging_class():
"""Test debugging a class with two methods."""
@debug
def should_raise(self):
raise Exception("Something bad happened")
class DebuggedClass(object):
def first_method(self):
raise Exception()

def second_method(self):
raise Exception()

debugged_object = DebuggedClass()

with capture_output(), patch('bdb.Bdb.set_trace') as set_trace:
debugged_object.first_method()
assert set_trace.called

with capture_output(), patch('bdb.Bdb.set_trace') as set_trace:
debugged_object.second_method()
assert set_trace.called


def test_debugging_non_compatible_type():
"""Test raising an indicative error when trying to debug a bad type."""
with pytest.raises(TypeError,
match="Debugger can only wrap functions and classes. "
"Got object 1 of type int"):
debug(1)


def test_debugging_when_source_code_is_missing():
"""Test debugging code that its source code is not available.

Note:
In this kind of code we cannot stop at an error, so we fall-back to
simply running this code without interference.
"""
exec("def function(): 1 / 0", locals(), globals())
func = debug(globals()["function"])

with pytest.raises(ArithmeticError):
func()


def test_ignoring_exceptions():
"""Test ignoring specific exceptions that should be raised."""
def func():
raise ValueError()

func = debug(func, ignore_exceptions=[ValueError])

with pytest.raises(ValueError):
func()


def test_targeting_specific_exception():
"""Test targeting specific exception that we should stop at it."""
def func():
assert False

func = debug(func, catch_exception=AssertionError)

with capture_output(), patch('bdb.Bdb.set_trace') as set_trace:
func()
assert set_trace.called

@patch('bdb.Bdb.set_trace')
def test_should_raise(self, set_trace):
with capture_output():
self.should_raise()
assert set_trace.called

@patch('bdb.Bdb.set_trace')
def test_shouldnt_raise(self, set_trace):
with capture_output():
self.shouldnt_raise()
assert not set_trace.called
def test_non_targeted_exceptions():
"""Test raising exceptions that don't match the targeted exception."""
def func():
raise ValueError()

func = debug(func, catch_exception=AssertionError)

if __name__ == '__main__':
main()
with pytest.raises(ValueError):
func()
13 changes: 11 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,20 @@ envlist = py27,py36

[testenv]


deps =
-r{toxinidir}/requirements.txt

commands =
flake8 setup.py ipdbugger
pylint setup.py ipdbugger
python tests/unit/test_debug.py
pytest

[pytest]
testpaths = tests/
addopts = --cov-report=html --cov=ipdbugger

[coverage:run]
branch = True

[coverage:report]
exclude_lines = if sys.version_info