Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 15fb9f8

Browse filesBrowse files
committed
Enhance unit tests (cztomczak#59).
Display summary with real number of tests ran including sub-tests in main_test. Ensure that messages are coming from Javascript in OnConsoleMessage. Automate checking for True/False asserts in ClientHandler and External.
1 parent 1aabf8e commit 15fb9f8
Copy full SHA for 15fb9f8

File tree

Expand file treeCollapse file tree

3 files changed

+108
-75
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

3 files changed

+108
-75
lines changed
Open diff view settings
Collapse file
+9-6Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"""Run unit tests. With no arguments all tests are run. Read notes below.
44
55
Usage:
6-
_runner.py [FILE | _TESTCASE]
6+
_test_runner.py [FILE | _TESTCASE]
77
88
Options:
99
FILE Run tests from single file
@@ -83,7 +83,7 @@ def run_testcase(self, testcase):
8383
self._discover("[!_]*.py", testcase)
8484
assert not self._count_suites(self._isolated_suites)
8585
if not self._count_suites(self._suites):
86-
print("[_runner.py] ERROR: test case not found")
86+
print("[_test_runner.py] ERROR: test case not found")
8787
sys.exit(1)
8888
# Import errors found during discovery are ignored
8989
self._run_suites(self._suites)
@@ -140,14 +140,17 @@ def _run_suites_in_isolation(self, suites):
140140
# Run test using new instance of Python interpreter
141141
try:
142142
output = subprocess.check_output(
143-
["python", "_runner.py", testcase_id],
143+
["python", "_test_runner.py", testcase_id],
144144
stderr=subprocess.STDOUT)
145145
exit_code = 0
146146
except subprocess.CalledProcessError as exc:
147147
output = exc.output
148148
exit_code = exc.returncode
149149
if type(output) != str:
150150
output = output.decode("utf-8", errors="replace")
151+
match = re.search(r"Ran (\d+) sub-tests in \w+", output)
152+
if match:
153+
self.ran += int(match.group(1))
151154
sys.stdout.write(output)
152155
# If tests failed parse output for errors/failures
153156
if exit_code:
@@ -228,9 +231,9 @@ def _print_summary(self):
228231
# type: () -> None
229232
"""Print summary and exit."""
230233
print("-"*70)
231-
print("[_runner.py] Ran "+str(self.ran)+" tests in total")
234+
print("[_test_runner.py] Ran "+str(self.ran)+" tests in total")
232235
if self.errors or self.failures:
233-
failed_str = "[_runner.py] FAILED ("
236+
failed_str = "[_test_runner.py] FAILED ("
234237
if self.failures:
235238
failed_str += ("failures="+str(self.failures))
236239
if self.errors:
@@ -240,7 +243,7 @@ def _print_summary(self):
240243
failed_str += ")"
241244
print(failed_str)
242245
else:
243-
print("[_runner.py] OK")
246+
print("[_test_runner.py] OK")
244247
self._exit()
245248

246249
def _exit(self):
Collapse file

‎unittests/isolated_test.py‎

Copy file name to clipboardExpand all lines: unittests/isolated_test.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import unittest
88
# noinspection PyUnresolvedReferences
9-
import _runner
9+
import _test_runner
1010
from os.path import basename
1111

1212
# Globals
@@ -35,4 +35,4 @@ def test_isolated3(self):
3535

3636

3737
if __name__ == "__main__":
38-
_runner.main(basename(__file__))
38+
_test_runner.main(basename(__file__))
Collapse file

‎unittests/main_test.py‎

Copy file name to clipboard
+97-67Lines changed: 97 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
"""General testing of CEF Python."""
22

3-
# To show the window for an extended period of time increase this number.
4-
MESSAGE_LOOP_RANGE = 25 # each iteration is 0.01 sec
5-
63
import unittest
74
# noinspection PyUnresolvedReferences
8-
import _runner
5+
import _test_runner
96
from os.path import basename
107
from cefpython3 import cefpython as cef
118
import time
129
import base64
10+
import sys
11+
12+
# To show the window for an extended period of time increase this number.
13+
MESSAGE_LOOP_RANGE = 25 # each iteration is 0.01 sec
1314

1415
g_browser = None
1516
g_client_handler = None
@@ -27,36 +28,41 @@
2728
</style>
2829
<script>
2930
function print(msg) {
31+
console.log(msg+" [JS]");
3032
msg = msg.replace("ok", "<b style='color:green'>ok</b>");
3133
msg = msg.replace("error", "<b style='color:red'>error</b>");
3234
document.getElementById("console").innerHTML += msg+"<br>";
3335
}
3436
window.onload = function(){
3537
print("window.onload() ok");
3638
37-
print("test_property1 = <i>"+test_property1+"</i>")
39+
// Test binding property: test_property1
3840
if (test_property1 == "Test binding property to the 'window' object") {
39-
print("ok");
41+
print("test_property_1 ok");
4042
} else {
41-
print("error");
42-
throw "test_property1 contains invalid string";
43+
throw new Error("test_property1 contains invalid string");
4344
}
4445
45-
print("test_property2 = <i>"+JSON.stringify(test_property2)+"</i>");
46+
// Test binding property: test_property2
4647
if (JSON.stringify(test_property2) == '{"key1":"Test binding property'+
4748
' to the \\'window\\' object","key2":["Inside list",1,2]}') {
48-
print("ok");
49+
print("test_property2 ok");
4950
} else {
50-
print("error");
51-
throw "test_property2 contains invalid value";
51+
throw new Error("test_property2 contains invalid value");
5252
}
5353
54+
// Test binding function: test_function
5455
test_function();
5556
print("test_function() ok");
5657
58+
// Test binding external object and use of javascript<>python callbacks
5759
external.test_callbacks(function(msg_from_python, py_callback){
58-
print("test_callbacks(): "+msg_from_python+" ok")
59-
print("py_callback.toString()="+py_callback.toString());
60+
if (msg_from_python == "String sent from Python") {
61+
print("test_callbacks() ok");
62+
} else {
63+
throw new Error("test_callbacks(): msg_from_python contains"+
64+
" invalid value");
65+
}
6066
py_callback("String sent from Javascript");
6167
print("py_callback() ok");
6268
});
@@ -73,34 +79,48 @@
7379
g_datauri = "data:text/html;base64,"+base64.b64encode(g_datauri_data.encode(
7480
"utf-8", "replace")).decode("utf-8", "replace")
7581

82+
g_subtests_ran = 0
83+
84+
85+
def subtest_message(message):
86+
global g_subtests_ran
87+
g_subtests_ran += 1
88+
print(str(g_subtests_ran) + ". " + message)
89+
sys.stdout.flush()
90+
7691

7792
class MainTest_IsolatedTest(unittest.TestCase):
7893

7994
def test_main(self):
8095
"""Main entry point."""
8196
# All this code must run inside one single test, otherwise strange
8297
# things happen.
98+
print("")
8399

84100
# Test initialization of CEF
85101
cef.Initialize({
86102
"debug": False,
87103
"log_severity": cef.LOGSEVERITY_ERROR,
88104
"log_file": "",
89105
})
106+
subtest_message("cef.Initialize() ok")
90107

91108
# Test global client callback
92109
global g_client_handler
93110
g_client_handler = ClientHandler(self)
94111
cef.SetGlobalClientCallback("OnAfterCreated",
95112
g_client_handler._OnAfterCreated)
113+
subtest_message("cef.SetGlobalClientCallback() ok")
96114

97115
# Test creation of browser
98116
global g_browser
99117
g_browser = cef.CreateBrowserSync(url=g_datauri)
100118
self.assertIsNotNone(g_browser, "Browser object")
119+
subtest_message("cef.CreateBrowserSync() ok")
101120

102121
# Test client handler
103122
g_browser.SetClientHandler(g_client_handler)
123+
subtest_message("browser.SetClientHandler() ok")
104124

105125
# Test javascript bindings
106126
global g_external
@@ -112,70 +132,76 @@ def test_main(self):
112132
bindings.SetProperty("test_property2", g_external.test_property2)
113133
bindings.SetObject("external", g_external)
114134
g_browser.SetJavascriptBindings(bindings)
135+
subtest_message("browser.SetJavascriptBindings() ok")
115136

116137
# Run message loop for 0.5 sec.
117138
# noinspection PyTypeChecker
118139
for i in range(MESSAGE_LOOP_RANGE):
119140
cef.MessageLoopWork()
120141
time.sleep(0.01)
142+
subtest_message("cef.MessageLoopWork() ok")
121143

122144
# Test browser closing. Remember to clean reference.
123145
g_browser.CloseBrowser(True)
124146
g_browser = None
147+
subtest_message("browser.CloseBrowser() ok")
125148

126149
# Give it some time to close before calling shutdown.
127150
# noinspection PyTypeChecker
128151
for i in range(25):
129152
cef.MessageLoopWork()
130153
time.sleep(0.01)
131154

132-
# Client handler asserts
133-
self.assertTrue(g_client_handler.OnAfterCreated_called,
134-
"OnAfterCreated() call")
135-
self.assertTrue(g_client_handler.OnLoadStart_called,
136-
"OnLoadStart() call")
137-
self.assertTrue(g_client_handler.OnLoadEnd_called,
138-
"OnLoadEnd() call")
139-
self.assertTrue(g_client_handler.FrameSourceVisitor_called,
140-
"FrameSourceVisitor.Visit() call")
141-
self.assertEqual(g_client_handler.javascript_errors, 0,
142-
"Javascript errors caught in OnConsoleMessage")
143-
144-
# Javascript asserts
145-
self.assertTrue(g_external.test_function_called,
146-
"js test_function() call")
147-
self.assertTrue(g_external.test_callbacks_called,
148-
"js external.test_callbacks() call")
149-
self.assertTrue(g_external.py_callback_called,
150-
"py_callback() call from js external.test_callbacks()")
155+
# Client handler asserts and javascript External asserts
156+
for obj in [g_client_handler, g_external]:
157+
test_for_True = False # Test whether asserts are working correctly
158+
for key, value in obj.__dict__.items():
159+
if key == "test_for_True":
160+
test_for_True = True
161+
continue
162+
if "_True" in key:
163+
self.assertTrue(value, "Check assert: "+key)
164+
subtest_message(obj.__class__.__name__ + "." +
165+
key.replace("_True", "") +
166+
" ok")
167+
elif "_False" in key:
168+
self.assertFalse(value, "Check assert: "+key)
169+
subtest_message(obj.__class__.__name__ + "." +
170+
key.replace("_False", "") +
171+
" ok")
172+
self.assertTrue(test_for_True)
151173

152174
# Test shutdown of CEF
153175
cef.Shutdown()
176+
subtest_message("cef.Shutdown() ok")
154177

178+
# Display real number of tests there were run
179+
print("\nRan " + str(g_subtests_ran) + " sub-tests in test_main")
180+
sys.stdout.flush()
155181

156-
class ClientHandler:
157-
test_case = None
158-
159-
OnAfterCreated_called = False
160-
OnLoadStart_called = False
161-
OnLoadEnd_called = False
162-
163-
FrameSourceVisitor_called = False
164-
frame_source_visitor = None
165-
166-
javascript_errors = 0
167182

183+
class ClientHandler(object):
168184
def __init__(self, test_case):
169185
self.test_case = test_case
186+
self.frame_source_visitor = None
187+
188+
# Asserts for True/False will be checked just before shutdown
189+
self.test_for_True = True # Test whether asserts are working correctly
190+
self.OnAfterCreated_True = False
191+
self.OnLoadStart_True = False
192+
self.OnLoadEnd_True = False
193+
self.FrameSourceVisitor_True = False
194+
self.javascript_errors_False = False
195+
self.OnConsoleMessage_True = False
170196

171197
# noinspection PyUnusedLocal
172198
def _OnAfterCreated(self, browser):
173-
self.OnAfterCreated_called = True
199+
self.OnAfterCreated_True = True
174200

175201
# noinspection PyUnusedLocal
176202
def OnLoadStart(self, browser, frame):
177203
self.test_case.assertEqual(browser.GetUrl(), g_datauri)
178-
self.OnLoadStart_called = True
204+
self.OnLoadStart_True = True
179205

180206
# noinspection PyUnusedLocal
181207
def OnLoadEnd(self, browser, frame, http_code):
@@ -184,18 +210,21 @@ def OnLoadEnd(self, browser, frame, http_code):
184210
frame.GetSource(self.frame_source_visitor)
185211
browser.ExecuteJavascript(
186212
"print('ClientHandler.OnLoadEnd() ok')")
187-
self.OnLoadEnd_called = True
213+
self.OnLoadEnd_True = True
188214

189215
# noinspection PyUnusedLocal
190216
def OnConsoleMessage(self, browser, message, source, line):
191217
if "error" in message.lower() or "uncaught" in message.lower():
192-
self.javascript_errors += 1
218+
self.javascript_errors_False = True
193219
raise Exception(message)
220+
else:
221+
# Confirmation that messages from javascript are coming
222+
self.OnConsoleMessage_True = True
223+
subtest_message(message)
194224

195225

196-
class FrameSourceVisitor:
197-
client_handler = None
198-
test_case = None
226+
class FrameSourceVisitor(object):
227+
"""Visitor for Frame.GetSource()."""
199228

200229
def __init__(self, client_handler, test_case):
201230
self.client_handler = client_handler
@@ -205,38 +234,39 @@ def __init__(self, client_handler, test_case):
205234
def Visit(self, value):
206235
self.test_case.assertIn("747ef3e6011b6a61e6b3c6e54bdd2dee",
207236
g_datauri_data)
208-
self.client_handler.FrameSourceVisitor_called = True
237+
self.client_handler.FrameSourceVisitor_True = True
209238

210239

211-
class External:
240+
class External(object):
212241
"""Javascript 'window.external' object."""
213-
test_case = None
214-
215-
# Test binding properties to the 'window' object.
216-
test_property1 = "Test binding property to the 'window' object"
217-
test_property2 = {"key1": test_property1,
218-
"key2": ["Inside list", 1, 2]}
219-
220-
test_function_called = False
221-
test_callbacks_called = False
222-
py_callback_called = False
223242

224243
def __init__(self, test_case):
225244
self.test_case = test_case
226245

246+
# Test binding properties to the 'window' object.
247+
self.test_property1 = "Test binding property to the 'window' object"
248+
self.test_property2 = {"key1": self.test_property1,
249+
"key2": ["Inside list", 1, 2]}
250+
251+
# Asserts for True/False will be checked just before shutdown
252+
self.test_for_True = True # Test whether asserts are working correctly
253+
self.test_function_True = False
254+
self.test_callbacks_True = False
255+
self.py_callback_True = False
256+
227257
def test_function(self):
228258
"""Test binding function to the 'window' object."""
229-
self.test_function_called = True
259+
self.test_function_True = True
230260

231261
def test_callbacks(self, js_callback):
232262
"""Test both javascript and python callbacks."""
233263
def py_callback(msg_from_js):
234264
self.test_case.assertEqual(msg_from_js,
235265
"String sent from Javascript")
236-
self.py_callback_called = True
266+
self.py_callback_True = True
237267
js_callback.Call("String sent from Python", py_callback)
238-
self.test_callbacks_called = True
268+
self.test_callbacks_True = True
239269

240270

241271
if __name__ == "__main__":
242-
_runner.main(basename(__file__))
272+
_test_runner.main(basename(__file__))

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.