how to write tests in Leo?

38 views
Skip to first unread message

HaveF HaveF

unread,
Dec 26, 2023, 9:44:46 PM12/26/23
to leo-editor
Hello, there,

My intuitive thought is that there are two types of tests in Leo,


1. Testing of common Python function script nodes,


2. Tests that require a Leo context, such as g, c, p, etc.

    2.1 Test with Leo already open, because there are already g, c, p

    2.2 Testing without Leo open. It is no different from a normal python program. e.g. 'python -m unittest'


For 1, if I have such a Leo script node, can I test it?


```
def add(a, b):
    return a + b

import unittest
class TestAddFunction(unittest.TestCase):

    def test_add(self):
        self.assertEqual(add(1, 2), 3)
        self.assertEqual(add(-1, 1), 0)
        self.assertEqual(add(-1, -1), -2)
```


For 2, Is this possible for the case in 2.1?


I flipped through the posts in the forums and it looked like there should be a 'test-' command, but I only had 'test-one' in my environment, nothing else. `execute-pytest` command also not works(maybe I am doing something wrong)


I failed to find anything in the documentation that made me start. Am I doing something wrong?



Thanks!

Thomas Passin

unread,
Dec 26, 2023, 9:53:48 PM12/26/23
to leo-editor
Take a look in the leo-editor\leo\unittests directory.  For example, test_gui.py imports g. etc.  Maybe that will be enough to get started.

HaveF HaveF

unread,
Dec 26, 2023, 10:09:35 PM12/26/23
to leo-e...@googlegroups.com
Take a look in the leo-editor\leo\unittests directory.  For example, test_gui.py imports g. etc.  Maybe that will be enough to get started.

My intuitive thought is that there are two types of tests in Leo,


1. Testing of common Python function script nodes,


2. Tests that require a Leo context, such as g, c, p, etc.

    2.1 Test with Leo already open, because there are already g, c, p

    2.2 Testing without Leo open. It is no different from a normal python program. e.g. 'python -m unittest'


Thanks, Thomas, I checked, but failed to understand, that is for 2.2 scene, right?

My main question is about 1, and 2.1 scenarios. How to perform specific operations in Leo, not how the code should be written

Thomas Passin

unread,
Dec 26, 2023, 11:40:18 PM12/26/23
to leo-editor
I don't have much understanding of Leo's tests myself.  I think that your case 1 would be handled by opening a NullGui.  This will give you a working g, from which you can access a lot of Leo's functionality.  I'm not sure how to deal with getting a commander with a null gui.  But there must be some test in Leo's source tree that could be a model.

For example, in leo/unittests/core, I see a file test_leoColorizer.py. It has a class TestColorizer(LeoUnitTest), which includes:

from leo.core import leoGlobals as g
from leo.core.leoTest2 import LeoUnitTest
from leo.core.leoQt import Qt
import leo.core.leoColorizer as leoColorizer
# ...
    """Test cases for leoColorizer.py"""
    def color(self, language_name, text):
        """Run the test by colorizing a node with the given text."""
        c = self.c
        c.p.b = text.replace('> >', '>>').replace('< <', '<<')
        c.recolor_now()


Looking in LeoPyRef for the base class LeoUnitTest, I find it in leoTest2.py. When I run py -m pytest in Leo's top directory, it runs all these many tests but does I never see a visible Leo window.  So in those unit test files are all the techniques to do what you want.

Edward K. Ream

unread,
Dec 27, 2023, 2:43:50 AM12/27/23
to leo-e...@googlegroups.com
On Tue, Dec 26, 2023 at 8:44 PM HaveF HaveF <iamap...@gmail.com> wrote:

My intuitive thought is that there are two types of tests in Leo,


1. Testing of common Python function script nodes,


2. Tests that require a Leo context, such as g, c, p, etc.


LeoPyRef.leo contains two direct children of the top-level "Code" node:

- Testing
- leo/unittests

 Like Thomas says, the second node contains all of Leo's unit tests.

The first node contains a single node, @file leoTest2.py, whose children are:

- << leoTest2 imports & annotations >>
- function.create_app
- class LeoUnitTest(unittest.TestCase)

The LeoUnitTest class invokes the magic that supports c, g, and p in Leo's unit test. Its top-level node defines the setUpClass method:

@classmethod
def setUpClass(cls: Any) -> None:
    create_app(gui_name='null')

In other words, any subclass of LeoUnitTest will call create_app before running any unit test.

So create_app is the source of the magic. This function creates a complete Leo application running with a null gui. It's similar to code in Leo's bridge.

As you can see, the test classes in leo/unittests are all subclasses (directly or indirectly) of LeoUnitTest. Some classes override their setUpClass or setUp methods.

Summary

The starting point for any question about how Leo works is LeoPyRef.leo.

I'm always willing to answer questions about LeoPyRef.leo.

How many times must I say this?

Edward

Edward K. Ream

unread,
Dec 27, 2023, 2:56:38 AM12/27/23
to leo-e...@googlegroups.com
On Tue, Dec 26, 2023 at 9:09 PM HaveF HaveF <iamap...@gmail.com> wrote:

> My main question is about 1, and 2.1 scenarios. How to perform specific operations in Leo, not how the code should be written.

All Leonine test classes should be subclasses of LeoUnitTest.

If your tests don't need c, g, or p, they can appear in subclasses of unittest.TestCase.

Edward

HaveF HaveF

unread,
Dec 27, 2023, 3:21:18 AM12/27/23
to leo-e...@googlegroups.com

I understand what you're saying, but I still can't seem to explain my problem well.


But for now, that's it. I'll wait until I read more LeoPyRef.


Thank you so much

Edward K. Ream

unread,
Dec 27, 2023, 6:37:16 AM12/27/23
to leo-e...@googlegroups.com
On Wed, Dec 27, 2023 at 2:21 AM HaveF HaveF <iamap...@gmail.com> wrote:

I understand what you're saying, but I still can't seem to explain my problem well.


But for now, that's it. I'll wait until I read more LeoPyRef.


Fair enough. I'm always glad to answer questions.

Thank you so much


You're welcome.

Edward
Reply all
Reply to author
Forward
0 new messages