-1

According to nosetest's API documentation, there is a LazySuite() class which is

class nose.suite.LazySuite(tests=())
A suite that may use a generator as its list of tests

However, I could not find any example how this test generator is supposed to look like. I tried to write one the way that one would use when yielding test cases to nosetest's test discovery and pass it to the LazySuite constructor as follows:

import nose
import nose.suite

data = [
        ['a', 'b', 'c'],
        ['1', '2', '3']
]

def check_data_list(data_list):
    assert data_list[0] == 'a'


def test_generator():
    for data_list in data:
        yield check_data_list, data_list


if __name__ == '__main__':

    suite = nose.suite.LazySuite(tests=test_generator())
    nose.run(suite=suite)

This, however, fails with

Traceback (most recent call last):
  File "test-with-nose.py", line 43, in <module>
    nose.run(suite=suite)
  File "/usr/local/lib/python3.5/dist-packages/nose/core.py", line 301, in run
    return TestProgram(*arg, **kw).success
  File "/usr/local/lib/python3.5/dist-packages/nose/core.py", line 121, in __init__
    **extra_args)
  File "/usr/lib/python3.5/unittest/main.py", line 94, in __init__
    self.runTests()
  File "/usr/local/lib/python3.5/dist-packages/nose/core.py", line 207, in runTests
    result = self.testRunner.run(self.test)
  File "/usr/local/lib/python3.5/dist-packages/nose/core.py", line 62, in run
    test(result)
  File "/usr/local/lib/python3.5/dist-packages/nose/suite.py", line 178, in __call__
    return self.run(*arg, **kw)
  File "/usr/local/lib/python3.5/dist-packages/nose/suite.py", line 225, in run
    test(orig)
  File "/usr/lib/python3.5/unittest/suite.py", line 84, in __call__
    return self.run(*args, **kwds)
  File "/usr/local/lib/python3.5/dist-packages/nose/suite.py", line 76, in run
    test(result)
TypeError: 'tuple' object is not callable

What is the generator for creating an instance of the LazySuite class supposed to look like instead?

Dirk
  • 9,381
  • 17
  • 70
  • 98

1 Answers1

0

Alright, I am not sure whether this is the only and correct way since I do not see it officially documented anywhere but it works when involving the TestLoader class and its loadTestsFromGenerator() method. This method gets passed a generator function which yields one or more of the (test_function, other_args, ...) tuples which I already mentioned in the question.

Full example (print statements are only for easier following of what is going on):

import nose
import nose.suite
import itertools
from nose.loader import TestLoader


data = [
        ['a', 'b', 'c'],
        ['1', '2', '3']
]

def first_check(row):
    print('Running first check on row: {0}'.format(row))
    assert row[0] is not None


def second_check(row):
    print('Running second check on row: {0}'.format(row))
    assert row[1] is not None

def test_generator():
    for row in data:
        yield first_check, row
        yield second_check, row

if __name__ == '__main__':
    all_tests = TestLoader().loadTestsFromGenerator(test_generator, 'test-with-nose')
    suite = nose.suite.LazySuite(all_tests)
    nose.main(suite=suite)

Running this with the --nocapture option (otherwise the prints will be hidden) gives:

Running first check on row: ['a', 'b', 'c']
.Running second check on row: ['a', 'b', 'c']
.Running first check on row: ['1', '2', '3']
.Running second check on row: ['1', '2', '3']
.
----------------------------------------------------------------------
Ran 4 tests in 0.002s

OK

Doing this for a large amount of to be tested rows (e.g. by yielding them from a csv reader instead of a nested list) is not really fast, however, it keeps the memory consumption low as only one combination out of row and test should be loaded in memory at the same time.

edit: This still keeps eating my precious memory when I execute the script for a very large generator (e.g. csv file with millions of rows), slowly but constantly. Could that be because the test results are still stored somewhere internally until all tests have been run?

Dirk
  • 9,381
  • 17
  • 70
  • 98