On Tuesday, December 7, 2021 at 9:03:33 AM UTC+1 Edward K. Ream wrote:

>
>  The assert* methods of unittest.TestCase provide better reports than 
> python's assert statement.
>  
>
Leo's existing test framework works well with the assert* methods, so the 
> conversion should be easy.
>
>
Have you tried using pytest as runner. The report it generates on a simple 
python assert statement with somewhat complex expressions is astonishing. 
Much better than any report TestCase.assert would produce. For example try 
this:
def test_dummy():
   a = [1, 2, ['a', 'b', 'f', 'd', 'e', 'c'], 4, 6]
   b = [1, 2, ['a', 'b', 'c', 'd', 'e', 'f'], 4, 5] 

   assert a == b

Running pytest -v on this function I get the following report:


    def test_dummy():
        a = [1, 2, ['a', 'b', 'f', 'd', 'e', 'c'], 4, 6]
        b = [1, 2, ['a', 'b', 'c', 'd', 'e', 'f'], 4, 5]
    
>       assert a == b
E       AssertionError: assert [1, 2, ['a', ...', 'c'], 4, 6] == [1, 2, 
['a', ...', 'f'], 4, 5]
E         At index 2 diff: ['a', 'b', 'f', 'd', 'e', 'c'] != ['a', 'b', 
'c', 'd', 'e', 'f']
E         Full diff:
E         - [1, 2, ['a', 'b', 'c', 'd', 'e', 'f'], 4, 5]
E         ?                    ^              ^       ^
E         + [1, 2, ['a', 'b', 'f', 'd', 'e', 'c'], 4, 6]
E         ?                    ^              ^       ^

It makes it easy to spot where the difference exactly is without the need 
of writing special formatting code by hand. In another thread I've read 
that you don't like using pytest because it generates too much output. And 
yes I've tried to run all unit tests using pytest and there were huge 
amount of failures. But most of them were caused by an assertion inside Leo 
core, during the test setup phase. I think this is caused by executing 
`TestSyntax.test_that_leo_starts`. When I excluded this test with 
self.skipTest(), pytest finds exactly the same number of failures as 
unittest. In fact it has found one more. In test_leoImport.TestCython 
class, there was no at-others and the only method was not part of the 
class, so it never run.

Commit 2492a13f1 fixes both of this.

The methods compare_outlines and create_expected_outline rely on vnode_info 
which split_root doesn't populate.
 

> P.S. I see that the new python importer refers to linescanner.Target and 
> defines a Python_ScanState class. Eventually, we would like both to go 
> away. I'll experiment with making them optional.
>
>
There is another thing that bothers me with the present code. All importers 
are forced to export a scanner class, even if they don't use one. Those 
exported classes are gathered in g.app.atAutoDict and 
g.app.classDispatchDict. But then, later methods app.body_parser_for_ext, 
app.scanner_for_ext and app.scanner_for_at_auto each of them create a 
wrapper function that uses this importer class and returns it as a simple 
function.

By generating those wrappers in the leoApp, unnecessary coupling exists 
between importer modules and LeoApp. LeoApp must now about internal affairs 
of importer and also importers must create class and even override some 
unused methods even if they don't need a class. It would be much cleaner if 
importers export a function and not a class. That would much simpler (in 
fact a minimal) API. Every importer must export just one function f(p, txt) 
which should create outline from given text in the given position. How each 
of the importers achieve this is entirely up to them. Of course I don't 
intend to rewrite all importers, just to change what they export and how 
LeoApp uses that what is exported.

######## in LeoApp #####
# instead of
def get_importer_for(key):
    aClass = mydict.get(key)
    def f(s, parent):
        return aClass().run(s, parent)
    return f
# we could simply use
def get_importer_for(key):
    return mydict.get(key)

##### in X_Importer ####
# instead of
importer_dict = {
    'class': X_Importer,
    'extensions': [...],
}
# we could use
importer_dict = { 'func': X_Importer.do_import, 'extensions':[...] }

### and in the base scanner class
    ...
    @staticmethod
    def do_import(aClass):
        def f(s, parent):
            return aClass().run(s, parent)
        return f




-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/c9bcb9cd-f005-4105-b60e-3034aaea4d7an%40googlegroups.com.

Reply via email to