blob: 7eeed2fb8fb63cef677bc0bbab7ddd90277746c9 [file] [edit]
#!/usr/bin/env python3
# Copyright 2026 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import subprocess
import re
import sys
import json
import unittest
# The goal of this test is to verify e2e behavior of our test harness w.r.t how
# it reports test results.
class DevToolsTestHarness(unittest.TestCase):
def run_test_with_rdb(self, cmd_args):
cmd = [
"npm", "run", "rdb", "--", "vpython3", "third_party/node/node.py",
"--output"
] + cmd_args
process = subprocess.Popen(cmd,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
text=True)
stdout, stderr = process.communicate()
if getattr(self, 'debug_mode', False):
sys.stdout.write(stdout)
sys.stdout.write(stderr)
match = re.search(
r'rdb-stream: created invocation - .*?/ui/inv/([^\s"\']+)', stderr)
if not match:
match = re.search(r'invocations/([^\s"\']+)', stderr)
self.assertIsNotNone(
match,
f"Failed to find rdb invocation ID in the output.\nStdout: {stdout}\nStderr: {stderr}"
)
invocation_id = match.group(1)
if invocation_id.startswith('invocations/'):
invocation_id = invocation_id[len('invocations/'):]
query_cmd = ["rdb", "query", invocation_id, "-json"]
query_process = subprocess.run(query_cmd,
capture_output=True,
text=True)
self.assertEqual(query_process.returncode, 0,
f"rdb query failed: {query_process.stderr}")
results = []
for line in query_process.stdout.strip().split('\n'):
line = line.strip()
if not line or not line.startswith('{'):
continue
try:
data = json.loads(line)
if 'testResult' in data:
results.append(data['testResult'])
except json.JSONDecodeError:
pass
return results, process.returncode
def _resolve_test_file(self, test_file):
import os
import re
match = re.match(r'^(.*\.([tj]s))(.*)$', test_file)
if match:
path_part = match.group(1)
suffix = match.group(3)
else:
path_part = test_file
suffix = ""
if path_part.endswith(".ts"):
path_part = path_part[:-3] + ".js"
if path_part.startswith("out/Default/"):
pass
elif path_part.startswith("gen/"):
path_part = os.path.join("out/Default", path_part)
else:
path_part = os.path.join("out/Default/gen", path_part)
return os.path.abspath(path_part) + suffix
def run_unit_test(self, test_file):
abs_test_file = self._resolve_test_file(test_file)
return self.run_test_with_rdb([
"node_modules/karma/bin/karma", "start",
"out/Default/gen/test/unit/karma.conf.js", "--", abs_test_file
])
def run_e2e_test(self, test_file):
abs_test_file = self._resolve_test_file(test_file)
return self.run_test_with_rdb(
["out/Default/gen/test/harness/run-mocha.js", abs_test_file])
def test_unit(self):
results, exit_code = self.run_unit_test(
"test/harness/unit/unit.test.ts")
self.assertEqual(exit_code, 0)
self.assertEqual(
len(results), 1,
f"Expected exactly one test result, got {len(results)}")
self.assertEqual(
results[0].get('testId'),
'test/harness/unit/unit.test.ts:unit:should_run_a_basic_unit_test_successfully'
)
self.assertEqual(results[0].get('status'), 'PASS')
def test_e2e(self):
results, exit_code = self.run_e2e_test("test/harness/e2e/e2e.test.ts")
self.assertEqual(exit_code, 0)
self.assertEqual(
len(results), 1,
f"Expected exactly one test result, got {len(results)}")
self.assertEqual(
results[0].get('testId'),
'test/harness/e2e/e2e.test.ts:test_harness_e2e_fixture:should_run_a_basic_e2e_test_successfully'
)
self.assertEqual(results[0].get('status'), 'PASS')
def test_e2e_duplicate(self):
results, exit_code = self.run_e2e_test(
"test/harness/e2e/duplicate.test.ts")
self.assertEqual(exit_code, 1)
self.assertEqual(
len(results), 0,
f"Expected exactly 0 test result, got {len(results)}")
def test_unit_duplicate(self):
results, exit_code = self.run_unit_test(
"test/harness/unit/duplicate.test.ts")
self.assertEqual(exit_code, 1)
def test_unit_hooks(self):
results, exit_code = self.run_unit_test(
"test/harness/unit/hooks.test.ts")
self.assertEqual(exit_code, 1)
self.assertEqual(
len(results), 4,
f"Expected exactly 4 test results, got {len(results)}")
self.assertEqual(results[0].get('testId'),
'test/harness/unit/hooks.test.ts:block_1:run_1')
self.assertEqual(results[0].get('status'), 'FAIL')
self.assertEqual(results[1].get('testId'),
'test/harness/unit/hooks.test.ts:block_1:run_2')
self.assertEqual(results[1].get('status'), 'FAIL')
self.assertEqual(results[2].get('testId'),
'test/harness/unit/hooks.test.ts:block_2:run_3')
self.assertEqual(results[2].get('status'), 'PASS')
self.assertEqual(results[3].get('testId'),
'test/harness/unit/hooks.test.ts:block_2:run_4')
self.assertEqual(results[3].get('status'), 'PASS')
def test_unit_ids(self):
results, exit_code = self.run_unit_test(
"test/harness/unit/hooks.test.ts:block_2:run_3")
self.assertEqual(exit_code, 0)
self.assertEqual(
len(results), 1,
f"Expected exactly one test result, got {len(results)}")
self.assertEqual(results[0].get('testId'),
'test/harness/unit/hooks.test.ts:block_2:run_3')
self.assertEqual(results[0].get('status'), 'PASS')
def test_e2e_ids(self):
results, exit_code = self.run_e2e_test(
"test/harness/e2e/multiple.test.ts:multiple:run2")
self.assertEqual(exit_code, 0)
self.assertEqual(
len(results), 1,
f"Expected exactly one test result, got {len(results)}")
self.assertEqual(results[0].get('testId'),
'test/harness/e2e/multiple.test.ts:multiple:run2')
self.assertEqual(results[0].get('status'), 'PASS')
def test_e2e_errors(self):
results, exit_code = self.run_e2e_test(
"test/harness/e2e/errors.test.ts")
self.assertEqual(exit_code, 1)
self.assertEqual(
len(results), 4,
f"Expected exactly 4 test results, got {len(results)}")
self.assertEqual(results[0].get('testId'),
'test/harness/e2e/errors.test.ts:block_1:run_1')
self.assertEqual(results[0].get('status'), 'PASS')
self.assertEqual(results[1].get('testId'),
'test/harness/e2e/errors.test.ts:block_1:run_2')
self.assertEqual(results[1].get('status'), 'PASS')
self.assertEqual(results[2].get('testId'),
'test/harness/e2e/errors.test.ts:block_2:run_3')
self.assertEqual(results[2].get('status'), 'FAIL')
self.assertEqual(results[3].get('testId'),
'test/harness/e2e/errors.test.ts:block_2:run_4')
self.assertEqual(results[3].get('status'), 'PASS')
def test_e2e_repeat(self):
abs_test_file = self._resolve_test_file("test/harness/e2e/e2e.test.ts")
results, exit_code = self.run_test_with_rdb([
"out/Default/gen/test/harness/run-mocha.js", abs_test_file, "--",
"--repeat=2"
])
self.assertEqual(exit_code, 0)
self.assertEqual(
len(results), 2,
f"Expected exactly 2 test results, got {len(results)}")
# Initial test
self.assertEqual(
results[0].get('testId'),
'test/harness/e2e/e2e.test.ts:test_harness_e2e_fixture:should_run_a_basic_e2e_test_successfully'
)
self.assertEqual(results[0].get('status'), 'PASS')
# Repeated run
self.assertEqual(
results[1].get('testId'),
'test/harness/e2e/e2e.test.ts:test_harness_e2e_fixture:should_run_a_basic_e2e_test_successfully'
)
self.assertEqual(results[1].get('status'), 'PASS')
def test_unit_repeat(self):
abs_test_file = self._resolve_test_file(
"test/harness/unit/unit.test.ts")
results, exit_code = self.run_test_with_rdb([
"node_modules/karma/bin/karma", "start",
"out/Default/gen/test/unit/karma.conf.js", "--", abs_test_file,
"--repeat=2"
])
self.assertEqual(exit_code, 0)
self.assertEqual(
len(results), 2,
f"Expected exactly 2 test results, got {len(results)}")
self.assertEqual(
results[0].get('testId'),
'test/harness/unit/unit.test.ts:unit:should_run_a_basic_unit_test_successfully'
)
self.assertEqual(results[0].get('status'), 'PASS')
self.assertEqual(
results[1].get('testId'),
'test/harness/unit/unit.test.ts:unit:should_run_a_basic_unit_test_successfully'
)
self.assertEqual(results[1].get('status'), 'PASS')
if __name__ == '__main__':
if '--debug' in sys.argv:
DevToolsTestHarness.debug_mode = True
sys.argv.remove('--debug')
unittest.main()