commit 10d1423d93bc68114ed22d909e17e96aca621bbe Author: Damian Johnson atagar@torproject.org Date: Sat Oct 26 20:18:59 2013 -0700
Testing interpretor-style examples in our pydocs
Using python's doctest module to test interpretor examples (those with '>>>'). Unfortunately this doesn't include sphinx code blocks (those started with a '::') nor some of our examples that aren't easy to mock. --- stem/descriptor/router_status_entry.py | 3 ++- stem/exit_policy.py | 4 +-- stem/util/connection.py | 5 ++-- stem/util/str_tools.py | 6 +++++ stem/version.py | 2 +- test/settings.cfg | 1 + test/unit/doctest.py | 43 ++++++++++++++++++++++++++++++++ 7 files changed, 58 insertions(+), 6 deletions(-)
diff --git a/stem/descriptor/router_status_entry.py b/stem/descriptor/router_status_entry.py index 4018b22..6622b72 100644 --- a/stem/descriptor/router_status_entry.py +++ b/stem/descriptor/router_status_entry.py @@ -699,7 +699,8 @@ def _base64_to_hex(identity, validate, check_if_fingerprint = True):
::
- >>> _base64_to_hex('p1aag7VwarGxqctS7/fS0y5FU+s') + >>> from stem.descriptor.router_status_entry import _base64_to_hex + >>> _base64_to_hex('p1aag7VwarGxqctS7/fS0y5FU+s', True) 'A7569A83B5706AB1B1A9CB52EFF7D2D32E4553EB'
:param str identity: encoded fingerprint from the consensus diff --git a/stem/exit_policy.py b/stem/exit_policy.py index 0f033de..4664c57 100644 --- a/stem/exit_policy.py +++ b/stem/exit_policy.py @@ -228,11 +228,11 @@ class ExitPolicy(object):
>>> policy = ExitPolicy('accept *:80', 'accept *:443', 'reject *:*') >>> policy.summary() - "accept 80, 443" + 'accept 80, 443'
>>> policy = ExitPolicy('accept *:443', 'reject *:1-1024', 'accept *:*') >>> policy.summary() - "reject 1-442, 444-1024" + 'reject 1-442, 444-1024'
:returns: **str** with a concise summary for our policy """ diff --git a/stem/util/connection.py b/stem/util/connection.py index d21ab0d..6e87f94 100644 --- a/stem/util/connection.py +++ b/stem/util/connection.py @@ -403,11 +403,12 @@ def expand_ipv6_address(address):
::
+ >>> from stem.util.connection import expand_ipv6_address >>> expand_ipv6_address("2001:db8::ff00:42:8329") - "2001:0db8:0000:0000:0000:ff00:0042:8329" + '2001:0db8:0000:0000:0000:ff00:0042:8329'
>>> expand_ipv6_address("::") - "0000:0000:0000:0000:0000:0000:0000:0000" + '0000:0000:0000:0000:0000:0000:0000:0000'
:param str address: IPv6 address to be expanded
diff --git a/stem/util/str_tools.py b/stem/util/str_tools.py index 33d5e1b..100bd0c 100644 --- a/stem/util/str_tools.py +++ b/stem/util/str_tools.py @@ -109,6 +109,7 @@ def _to_camel_case(label, divider = "_", joiner = " "):
::
+ >>> from stem.util.str_tools import _to_camel_case >>> _to_camel_case("I_LIKE_PEPPERJACK!") 'I Like Pepperjack!'
@@ -141,6 +142,7 @@ def get_size_label(byte_count, decimal = 0, is_long = False, is_bytes = True):
::
+ >>> from stem.util.str_tools import get_size_label >>> get_size_label(2000000) '1 MB'
@@ -176,6 +178,7 @@ def get_time_label(seconds, decimal = 0, is_long = False):
::
+ >>> from stem.util.str_tools import get_time_label >>> get_time_label(10000) '2h'
@@ -203,6 +206,7 @@ def get_time_labels(seconds, is_long = False):
::
+ >>> from stem.util.str_tools import get_time_labels >>> get_time_labels(400) ['6m', '40s']
@@ -232,6 +236,7 @@ def get_short_time_label(seconds):
::
+ >>> from stem.util.str_tools import get_short_time_label >>> get_short_time_label(111) '01:51'
@@ -273,6 +278,7 @@ def parse_short_time_label(label):
::
+ >>> from stem.util.str_tools import parse_short_time_label >>> parse_short_time_label('01:51') 111
diff --git a/stem/version.py b/stem/version.py index 44f1d02..5efc1e0 100644 --- a/stem/version.py +++ b/stem/version.py @@ -11,7 +11,7 @@ easily parsed and compared, for instance...
my_version = get_system_tor_version() print my_version
0.2.1.30 - >>> my_version >= Requirement.CONTROL_SOCKET + >>> my_version >= Requirement.TORRC_CONTROL_SOCKET True
**Module Overview:** diff --git a/test/settings.cfg b/test/settings.cfg index 222a7a4..9717d24 100644 --- a/test/settings.cfg +++ b/test/settings.cfg @@ -184,6 +184,7 @@ test.unit_tests |test.unit.response.mapaddress.TestMapAddressResponse |test.unit.connection.authentication.TestAuthenticate |test.unit.control.controller.TestControl +|test.unit.doctest.TestDocumentation
test.integ_tests |test.integ.util.conf.TestConf diff --git a/test/unit/doctest.py b/test/unit/doctest.py new file mode 100644 index 0000000..cae58a7 --- /dev/null +++ b/test/unit/doctest.py @@ -0,0 +1,43 @@ +""" +Tests examples from our documentation. +""" + +from __future__ import absolute_import + +import doctest +import os +import unittest + +import stem.version + +import test.util + +try: + # added in python 3.3 + from unittest.mock import Mock, patch +except ImportError: + from mock import Mock, patch + + +class TestDocumentation(unittest.TestCase): + def test_examples(self): + cwd = os.getcwd() + + for path in test.util._get_files_with_suffix(os.path.join(test.util.STEM_BASE, 'stem')): + path = '../../' + path[len(cwd) + 1:] + test_run = None + + if path.endswith('/stem/util/conf.py'): + pass # too much context to easily test + elif path.endswith('/stem/response/__init__.py'): + pass # the escaped slashes seem to be confusing doctest + elif path.endswith('/stem/control.py'): + pass # examples refrence a control instance + elif path.endswith('/stem/version.py'): + with patch('stem.version.get_system_tor_version', Mock(return_value = stem.version.Version('0.2.1.30'))): + test_run = doctest.testfile(path) + else: + test_run = doctest.testfile(path) + + if test_run and test_run.failed > 0: + self.fail()