beeware / cricket

A GUI tool for running Python test suites.
BSD 3-Clause "New" or "Revised" License
213 stars 68 forks source link

'TestCase' object has no attribute 'timestamp' #39

Open MarkusH opened 9 years ago

MarkusH commented 9 years ago

On current Django master (django/django@19188826b4aa989475418f1ea9bf8631b04da1e8) I get a failure when running cricket-unittest from inside the tests directory:

Traceback (most recent call last):
  File "/home/markus/.venvs/django-dev-py27/bin/cricket-unittest", line 9, in <module>
    load_entry_point('cricket==0.2.3', 'console_scripts', 'cricket-unittest')()
  File "/home/markus/.venvs/django-dev-py27/lib/python2.7/site-packages/cricket/unittest/__main__.py", line 9, in main
    cricket_main(UnittestProject)
  File "/home/markus/.venvs/django-dev-py27/lib/python2.7/site-packages/cricket/main.py", line 72, in main
    project.refresh(test_list, errors)
  File "/home/markus/.venvs/django-dev-py27/lib/python2.7/site-packages/cricket/model.py", line 506, in refresh
    testModule._purge(timestamp)
  File "/home/markus/.venvs/django-dev-py27/lib/python2.7/site-packages/cricket/model.py", line 381, in _purge
    testModule._purge(timestamp)
  File "/home/markus/.venvs/django-dev-py27/lib/python2.7/site-packages/cricket/model.py", line 381, in _purge
    testModule._purge(timestamp)
  File "/home/markus/.venvs/django-dev-py27/lib/python2.7/site-packages/cricket/model.py", line 381, in _purge
    testModule._purge(timestamp)
  File "/home/markus/.venvs/django-dev-py27/lib/python2.7/site-packages/cricket/model.py", line 242, in _purge
    if testMethod.timestamp != timestamp:
AttributeError: 'TestCase' object has no attribute 'timestamp'
streamnsight commented 7 years ago

Having the same issue, although i had this running before. Can't figure how to run it again. Any insight on what this is about?

khushbuparakh commented 7 years ago

I am trying to reproduce the issue. But facing no error so far in the timestamp. @MarkusH any suggestions what you were trying to run exactly. I am also trying to run it from tests dir

streamnsight commented 7 years ago

I checked again and I am getting the error when NOT in the test dir, but it seems fine in the test dir.

khushbuparakh commented 7 years ago

@streamnsight would you mind providing the steps you are following?.

robcarney commented 7 years ago

This has been happening to me as well. When I run the "cricket-unittest" command from the main batavia directory I get the timestamp issue. Then, when I tried to run it from the tests directory I get:

File "/Users/robertcarney/PythonWorkspace/pybee/env/lib/python3.5/site-packages/cricket/model.py", line 381, in _purge AttributeError: 'TestMethod' object has no attribute '_purge'

Looking through the cricket source code, this seems accurate: the TestMethod class really does have no attribute '_purge', it looks like they're expecting a TestModule but getting a TestMethod instance. Any ideas?

AlexLloyd0 commented 7 years ago

@robcarney I'm getting the exact same thing. Did you make any progress with this?

@khushbuparakh I can't speak for the others, but I'm following the steps outlined here (on a Windows machine)

streamnsight commented 7 years ago

things worked fine for me when I ran cricket from the root of my repo. i got this error when I was in the wrong folder. go figure!

AlexLloyd0 commented 7 years ago

For each sub-directory of batavia-dev\batavia other than batavia-dev\batavia\tests the GUI appears with an empty list of tests.

From the guide linked above:

For the fun way, you need to install BeeWare's test-running tool, Cricket. Follow the installation instructions to install it into your virtualenv; then, in the batavia-dev/batavia directory, type:

$ cricket-unittest

(denv) C:\code\pybee\batavia-dev\batavia>cricket-unittest Traceback (most recent call last): File "c:\users\alex\appdata\local\programs\python\python34\lib\runpy.py", line 170, in _run_module_as_main "__main__", mod_spec) File "c:\users\alex\appdata\local\programs\python\python34\lib\runpy.py", line 85, in _run_code exec(code, run_globals) File "C:\Users\Alex\AppData\Local\Programs\Python\Python34\Scripts\cricket-unittest.exe\__main__.py", line 9, in <module> File "c:\users\alex\appdata\local\programs\python\python34\lib\site-packages\cricket\unittest\__main__.py", line 9, in main cricket_main(UnittestProject) File "c:\users\alex\appdata\local\programs\python\python34\lib\site-packages\cricket\main.py", line 74, in main project.refresh(test_list, errors) File "c:\users\alex\appdata\local\programs\python\python34\lib\site-packages\cricket\model.py", line 506, in refresh testModule._purge(timestamp) File "c:\users\alex\appdata\local\programs\python\python34\lib\site-packages\cricket\model.py", line 381, in _purge testModule._purge(timestamp) File "c:\users\alex\appdata\local\programs\python\python34\lib\site-packages\cricket\model.py", line 381, in _purge testModule._purge(timestamp) File "c:\users\alex\appdata\local\programs\python\python34\lib\site-packages\cricket\model.py", line 381, in _purge testModule._purge(timestamp) File "c:\users\alex\appdata\local\programs\python\python34\lib\site-packages\cricket\model.py", line 242, in _purge if testMethod.timestamp != timestamp: AttributeError: 'TestCase' object has no attribute 'timestamp'

Running python setup.py test in ...\batavia (usual unittest) works.

robcarney commented 7 years ago

Nothing yet, I've just been running the test script like you said. I'll troubleshoot more later. Out of curiosity, what python version are you using in your virtual environment @AlexLloyd1 ?

AlexLloyd0 commented 7 years ago

@robcarney 3.4.3, and you?

ghost commented 7 years ago

@robcarney @AlexLloyd1 I've had the same issue on Pythons 3.4, 3.5, and 3.6. EDIT: see pybee/batavia#585

I think the issue is located in cricket.model.Project.confirm_exists. confirm_exists is invoked by refresh on each test label to be tested and is responsible both for setting the timestamps on TestMethods and constructing a tree of tests modules/cases/methods with the Project as the root; as far as I can tell this is the only place timestamps are set. Then Project._purge walks the tree down until we hit a TestMethod with no timestamp - since confirm_exists is responsible for both timestamps and the tree, I think we have to start by looking at it.

ghost commented 7 years ago

@robcarney @AlexLloyd1 Found it; looks like it was a Batavia bug after all. In batavia/tests/modules/test_json.py lines 51, 52, and most importantly 56 all describe test methods named test_json_JSONEncoder().<meth>. The problem is that parentheses and periods are illegal characters in a Python identifier, and so when cricket is parsing dotted-paths to test methods at cricket/cricket/models.py, top of confirm_exists with parts = test_label.split('.') it thinks that test_json_JSONEncoder is a module, and <meth> (usually encode_something) is the method. Most likely this hasn't been caught on the Batavia side because they're using template metaprogamming to generate tests; I'm not sure, however, why unittest or pytest allow the illegal test method names.

Anyway that's the bug.

EDIT:

I should've said that's a bug. Referring to the error that occurs when running cricket-unittest from the tests directory:

File "/Users/robertcarney/PythonWorkspace/pybee/env/lib/python3.5/site-packages/cricket/model.py", line 381, in _purge
AttributeError: 'TestMethod' object has no attribute '_purge'

If you run from that same directory

python -m cricket.unittest.discoverer

you'll see that the import paths it is returning are very divergent from those that it returns when run in the root directory. I have not yet determined why this is or how exactly it breaks cricket.

robcarney commented 7 years ago

@jmsdvl Interesting, I'll take a look later. But good catch, thanks for looking into it

ghost commented 7 years ago

Ok here's what's happening with the error when running in the test directory.

cricket-unittest's test discovery is piggybacked on unittest.TestLoader().discover('.'), and if the value of '.' (current directory) is batavia/tests, all the relative imports in the test package are broken. Rather than throw ImportErrors (which would kill the test runner, preventing acceptable tests from running), unittest's discoverer wraps the unimportable test module in a unittest.loader._FailedTest object and puts it in the TestSuite. Then cricket's test discovery mechanism gives to Project.refresh a bunch of _FailedTest objects.

More precisely, it includes strings like:

unittest.loader._FailedTest.structures.test_while
unittest.loader._FailedTest.test_pystone

And then confirm_exists will place _FailedTest into the tree as a TestModule based on the first line of input, then overwrite that entry with a TestCase based on the second line of input. This breaks the tree and leads to the observed errors.

I think there's two problems here:

  1. If unittest fails at any point in loading / discovery (all discovered modules are imported as part of discovery and load), cricket doesn't know how to intelligently handle it.
  2. Cricket's assumption that all test functions can be grouped into cases, which can be grouped into modules, seems a bit shaky - for exactly the above reason, if no other.