Coverage for C:\Repos\leo-editor\leo\core\leoTest2.py: 98%
81 statements
« prev ^ index » next coverage.py v6.4, created at 2022-05-24 10:21 -0500
« prev ^ index » next coverage.py v6.4, created at 2022-05-24 10:21 -0500
1# -*- coding: utf-8 -*-
2#@+leo-ver=5-thin
3#@+node:ekr.20201129023817.1: * @file leoTest2.py
4#@@first
5"""
6Support for Leo's new unit tests, contained in leo/unittests/test_*.py.
8Run these tests using unittest or pytest from the command line.
9See g.run_unit_tests and g.run_coverage_tests.
11This file also contains classes that convert @test nodes in unitTest.leo to
12tests in leo/unittest. Eventually these classes will move to scripts.leo.
13"""
14import time
15import unittest
16import warnings
17from leo.core import leoGlobals as g
18from leo.core import leoApp
20#@+others
21#@+node:ekr.20201130195111.1: ** function.create_app
22def create_app(gui_name='null'):
23 """
24 Create the Leo application, g.app, the Gui, g.app.gui, and a commander.
26 This method is expensive (0.5 sec) only the first time it is called.
28 Thereafter, recreating g.app, g.app.gui, and new commands is fast.
29 """
30 trace = False
31 t1 = time.process_time()
32 #
33 # Set g.unitTesting *early*, for guards, to suppress the splash screen, etc.
34 g.unitTesting = True
35 # Create g.app now, to avoid circular dependencies.
36 g.app = leoApp.LeoApp()
37 # Late imports.
38 warnings.simplefilter("ignore")
39 from leo.core import leoConfig
40 from leo.core import leoNodes
41 from leo.core import leoCommands
42 from leo.core.leoGui import NullGui
43 if gui_name == 'qt':
44 from leo.plugins.qt_gui import LeoQtGui
45 t2 = time.process_time()
46 g.app.recentFilesManager = leoApp.RecentFilesManager()
47 g.app.loadManager = lm = leoApp.LoadManager()
48 lm.computeStandardDirectories()
49 g.app.leoID = 'TestLeoId' # 2022/03/06: Use a standard user id for all tests.
50 g.app.nodeIndices = leoNodes.NodeIndices(g.app.leoID)
51 g.app.config = leoConfig.GlobalConfigManager()
52 g.app.db = g.NullObject('g.app.db') # type:ignore
53 g.app.pluginsController = g.NullObject('g.app.pluginsController') # type:ignore
54 g.app.commander_cacher = g.NullObject('g.app.commander_cacher') # type:ignore
55 if gui_name == 'null':
56 g.app.gui = NullGui()
57 elif gui_name == 'qt':
58 g.app.gui = LeoQtGui()
59 else:
60 raise TypeError(f"create_gui: unknown gui_name: {gui_name!r}")
61 t3 = time.process_time()
62 # Create a dummy commander, to do the imports in c.initObjects.
63 # Always use a null gui to avoid screen flash.
64 # setUp will create another commander.
65 c = leoCommands.Commands(fileName=None, gui=g.app.gui)
66 # Create minimal config dictionaries.
67 settings_d, bindings_d = lm.createDefaultSettingsDicts()
68 lm.globalSettingsDict = settings_d
69 lm.globalBindingsDict = bindings_d
70 c.config.settingsDict = settings_d
71 c.config.bindingsDict = bindings_d
72 assert g.unitTesting is True # Defensive.
73 t4 = time.process_time()
74 # Trace times. This trace happens only once:
75 # imports: 0.016
76 # gui: 0.000
77 # commander: 0.469
78 # total: 0.484
79 if trace and t4 - t3 > 0.1:
80 print('create_app:\n'
81 f" imports: {(t2-t1):.3f}\n"
82 f" gui: {(t3-t2):.3f}\n"
83 f"commander: {(t4-t2):.3f}\n"
84 f" total: {(t4-t1):.3f}\n")
85 return c
86#@+node:ekr.20210902014907.1: ** class LeoUnitTest(unittest.TestCase)
87class LeoUnitTest(unittest.TestCase):
88 """
89 The base class for all unit tests in Leo.
91 Contains setUp/tearDown methods and various utilites.
92 """
93 #@+others
94 #@+node:ekr.20210901140855.2: *3* LeoUnitTest.setUp, tearDown & setUpClass
95 @classmethod
96 def setUpClass(cls):
97 create_app(gui_name='null')
99 def setUp(self):
100 """
101 Create a commander using a **null** gui, regardless of g.app.gui.
102 Create the nodes in the commander.
103 """
104 # Do the import here to avoid circular dependencies.
105 from leo.core import leoCommands
106 from leo.core.leoGui import NullGui
107 # Set g.unitTesting *early*, for guards.
108 g.unitTesting = True
109 # Create a new commander for each test.
110 # This is fast, because setUpClass has done all the imports.
111 self.c = c = leoCommands.Commands(fileName=None, gui=NullGui())
112 # Init the 'root' and '@settings' nodes.
113 self.root_p = c.rootPosition()
114 self.root_p.h = 'root'
115 self.settings_p = self.root_p.insertAfter()
116 self.settings_p.h = '@settings'
117 # Select the 'root' node.
118 c.selectPosition(self.root_p)
120 def tearDown(self):
121 self.c = None
122 #@+node:ekr.20210830151601.1: *3* LeoUnitTest.create_test_outline
123 def create_test_outline(self):
124 p = self.c.p
125 # Create the following outline:
126 #
127 # root
128 # child clone a
129 # node clone 1
130 # child b
131 # child clone a
132 # node clone 1
133 # child c
134 # node clone 1
135 # child clone a
136 # node clone 1
137 # child b
138 # child clone a
139 # node clone 1
140 assert p == self.root_p
141 assert p.h == 'root'
142 # Child a
143 child_clone_a = p.insertAsLastChild()
144 child_clone_a.h = 'child clone a'
145 node_clone_1 = child_clone_a.insertAsLastChild()
146 node_clone_1.h = 'node clone 1'
147 # Child b
148 child_b = p.insertAsLastChild()
149 child_b.h = 'child b'
150 # Clone 'child clone a'
151 clone = child_clone_a.clone()
152 clone.moveToLastChildOf(child_b)
153 # Child c
154 child_c = p.insertAsLastChild()
155 child_c.h = 'child c'
156 # Clone 'node clone 1'
157 clone = node_clone_1.clone()
158 clone.moveToLastChildOf(child_c)
159 # Clone 'child clone a'
160 clone = child_clone_a.clone()
161 clone.moveToLastChildOf(p)
162 # Clone 'child b'
163 clone = child_b.clone()
164 clone.moveToLastChildOf(p)
165 #@-others
166#@-others
167#@-leo