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

does green support doctest? #88

Closed
SamuraiT opened this issue Oct 2, 2015 · 7 comments
Closed

does green support doctest? #88

SamuraiT opened this issue Oct 2, 2015 · 7 comments

Comments

@SamuraiT
Copy link

SamuraiT commented Oct 2, 2015

Does green support doctest?
I am using doctest, but seems like green does not support doctest.

@CleanCut
Copy link
Owner

CleanCut commented Oct 2, 2015

Though I am familiar with the concept of doctests, I have never personally used them or even looked into them. So no, green does not currently support them unless our close ties to the built-in unittest framework brings it in for free.

Tell me, how do you usually write/run doctests? Is it part of unittest? Is it part of python? Is it a 3rd-party add-on? I'm curious.

@SamuraiT
Copy link
Author

SamuraiT commented Oct 3, 2015

all right. I am using just built-in doctest. let's say I have a file called foo.py which is

# foo.py
class Foo(object):

    def bar(sel):
        """
        >>> foo = Foo()
        >>> foo.bar()
        'foobar'
        """
        return "foobar"

and just run the test

$ python3 -m doctest -v foo.py

foo = Foo()
Expecting nothing
ok
Trying:
    foo.bar()
Expecting:
    'foobar'
ok
2 items had no tests:
    foo
    foo.Foo
1 items passed all tests:
   2 tests in foo.Foo.bar
2 tests in 3 items.
2 passed and 0 failed.
Test passed.

just like that, but as you can see, it's hard to understand the stdard output.
I wish you could solve it or I could help solving it

@CleanCut
Copy link
Owner

CleanCut commented Oct 5, 2015

I think it would be great if you gave it a try! That would be a wonderful feature to add to Green. I wonder if doctest uses unittest under the hood. If it does, that would be a great place to do the integration.

@SamuraiT
Copy link
Author

SamuraiT commented Oct 8, 2015

I never checked out that doctest runs under the unittest, I'll check it out.

@aperezdc
Copy link

@CleanCut @SamuraiT: It is possible to run doctests with unittest, by wrapping the doctests into a DocTestSuite or a DocFileSuite like in this example. AFAIK these classes provided by the doctest module have the same API as the unittest.TestSuite class, and that's how unittest is able to run them. Also, note how the linked example has a load_tests() function (related: #87) to let unittest know about the additional tests.

@charles-l
Copy link
Contributor

charles-l commented Nov 23, 2019

@aperezdc

I've built a test program to do this:

# test_doctest.py                                                                                                                                                                                                                                                                                                           
import doctest                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                               
def f():                                                                                                                                                                                                                                                                                                                       
    '''                                                                                                                                                                                                                                                                                                                        
    >>> f()                                                                                                                                                                                                                                                                                                                    
    2                                                                                                                                                                                                                                                                                                                          
    '''                                                                                                                                                                                                                                                                                                                        
    return 2                                                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                               
def load_tests(loader, tests, ignore):                                                                                                                                                                                                                                                                                         
    return doctest.DocTestSuite('test_doctest')

With unittest, it will run:

python3 -m unittest test_doctest.py

green currently hangs, but I submitted PR #214 to address that. When I run it now, I get the following error:

  File "/home/nc/Dev/green/green/process.py", line 335, in poolRunner                                                                                                                                                                                                                                                          
    result.startTest(test)                                                                                                                                                                                                                                                                                                     
  File "/home/nc/Dev/green/green/result.py", line 237, in startTest                                                                                                                                                                                                                                                            
    test = proto_test(test)                                                                                                                                                                                                                                                                                                    
  File "/home/nc/Dev/green/green/result.py", line 31, in proto_test                                                                                                                                                                                                                                                            
    return ProtoTest(test)                                                                                                                                                                                                                                                                                                     
  File "/home/nc/Dev/green/green/result.py", line 68, in __init__                                                                                                                                                                                                                                                              
    self.method_name = str(test).split()[0]                                                                                                                                                                                                                                                                                    
  File "/usr/lib/python3.8/unittest/suite.py", line 27, in __repr__                                                                                                                                                                                                                                                            
    return "<%s tests=%s>" % (util.strclass(self.__class__), list(self))                                                                                                                                                                                                                                                       
  File "/usr/lib/python3.8/doctest.py", line 2401, in __repr__                                                                                                                                                                                                                                                                 
    return self._dt_test.filename                                                                                                                                                                                                                                                                                              
AttributeError: 'str' object has no attribute 'filename'                                                                                                                                                                                                                                                                       

So it looks like at some part inside green the DocTestCase._dt_test field is getting turned into a string...

@CleanCut
Copy link
Owner

CleanCut commented Jan 4, 2020

Support for doctests was added in version 3.1.0, just released. It requires choosing which modules you want to execute doctests from (for example, lets say you have doctests in myproj.foo and myproj.bar), and then in one of your test modules that contains unit tests adding a doctest_modules = [ ... ] list containing the modules you want to import the doctests from. For example, if you had a test module:

# test_stuff.py
import unittest

class TestSomething(unittest.TestCase)
    def test_something(self):
        # You need to have at least one unittest TestCase subclass with a test method
        pass

# Then this will work
import myproj.foo
doctest_modules = [
    myproj.foo,  # An actual module is best, because then we don't have to "discover" it via the filesystem
    "myproj.bar"  # But you can indicate the module with a string if you must
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants