mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-27 07:40:59 +00:00
tests/ui: move files to ui_tests dir
This commit is contained in:
parent
e709f76b14
commit
2eda139ac4
@ -14,12 +14,7 @@
|
||||
# You should have received a copy of the License along with this library.
|
||||
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
|
||||
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
@ -29,8 +24,8 @@ from trezorlib.device import apply_settings, wipe as wipe_device
|
||||
from trezorlib.messages.PassphraseSourceType import HOST as PASSPHRASE_ON_HOST
|
||||
from trezorlib.transport import enumerate_devices, get_transport
|
||||
|
||||
from . import ui_tests
|
||||
from .device_handler import BackgroundDeviceHandler
|
||||
from .ui_tests.html import create_diff_doc
|
||||
|
||||
|
||||
def get_device():
|
||||
@ -54,118 +49,6 @@ def get_device():
|
||||
raise RuntimeError("No debuggable device found")
|
||||
|
||||
|
||||
def _get_test_dirname(node):
|
||||
# This composes the dirname from the test module name and test item name.
|
||||
# Test item name is usually function name, but when parametrization is used,
|
||||
# parameters are also part of the name. Some functions have very long parameter
|
||||
# names (tx hashes etc) that run out of maximum allowable filename length, so
|
||||
# we limit the name to first 100 chars. This is not a problem with txhashes.
|
||||
node_name = re.sub(r"\W+", "_", node.name)[:100]
|
||||
node_module_name = node.getparent(pytest.Module).name
|
||||
return "{}_{}".format(node_module_name, node_name)
|
||||
|
||||
|
||||
def _check_fixture_directory(fixture_dir, screen_path):
|
||||
# create the fixture dir if it does not exist
|
||||
if not fixture_dir.exists():
|
||||
fixture_dir.mkdir()
|
||||
|
||||
# delete old files
|
||||
shutil.rmtree(screen_path, ignore_errors=True)
|
||||
screen_path.mkdir()
|
||||
|
||||
|
||||
def _process_recorded(screen_path):
|
||||
records = sorted(screen_path.iterdir())
|
||||
|
||||
# create hash
|
||||
digest = _hash_files(records)
|
||||
with open(screen_path / "../hash.txt", "w") as f:
|
||||
f.write(digest)
|
||||
_rename_records(screen_path)
|
||||
|
||||
|
||||
def _rename_records(screen_path):
|
||||
# rename screenshots
|
||||
for index, record in enumerate(sorted(screen_path.iterdir())):
|
||||
filename = screen_path / "{:08}.png".format(index)
|
||||
record.replace(filename)
|
||||
|
||||
|
||||
def _hash_files(files):
|
||||
hasher = hashlib.sha256()
|
||||
for file in sorted(files):
|
||||
with open(file, "rb") as f:
|
||||
content = f.read()
|
||||
hasher.update(content)
|
||||
|
||||
return hasher.digest().hex()
|
||||
|
||||
|
||||
def _process_tested(fixture_test_path, test_name):
|
||||
hash_file = fixture_test_path / "hash.txt"
|
||||
|
||||
if not hash_file.exists():
|
||||
raise ValueError("File hash.txt not found.")
|
||||
|
||||
with open(hash_file, "r") as f:
|
||||
expected_hash = f.read()
|
||||
|
||||
actual_path = fixture_test_path / "actual"
|
||||
_rename_records(actual_path)
|
||||
|
||||
records = sorted(actual_path.iterdir())
|
||||
actual_hash = _hash_files(records)
|
||||
|
||||
if actual_hash != expected_hash:
|
||||
create_diff_doc(fixture_test_path, test_name, actual_hash, expected_hash)
|
||||
pytest.fail(
|
||||
"Hash of {} differs.\nExpected: {}\nActual: {}".format(
|
||||
test_name, expected_hash, actual_hash
|
||||
)
|
||||
)
|
||||
else:
|
||||
if (fixture_test_path / "diff.html").exists():
|
||||
(fixture_test_path / "diff.html").unlink()
|
||||
|
||||
|
||||
@contextmanager
|
||||
def _screen_recording(client, request):
|
||||
if not request.node.get_closest_marker("skip_ui"):
|
||||
test_screen = request.config.getoption("test_screen")
|
||||
else:
|
||||
test_screen = ""
|
||||
|
||||
if not test_screen:
|
||||
yield
|
||||
return
|
||||
|
||||
fixture_root = Path(__file__) / "../ui_tests/fixtures"
|
||||
test_name = _get_test_dirname(request.node)
|
||||
fixture_test_path = fixture_root.resolve() / test_name
|
||||
|
||||
if test_screen == "record":
|
||||
screen_path = fixture_test_path / "recorded"
|
||||
elif test_screen == "test":
|
||||
screen_path = fixture_test_path / "actual"
|
||||
else:
|
||||
raise ValueError("Invalid test_screen option.")
|
||||
|
||||
_check_fixture_directory(fixture_test_path, screen_path)
|
||||
|
||||
try:
|
||||
client.debug.start_recording(str(screen_path))
|
||||
yield
|
||||
finally:
|
||||
client.debug.stop_recording()
|
||||
if test_screen == "record":
|
||||
_process_recorded(screen_path)
|
||||
elif test_screen == "test":
|
||||
_process_tested(fixture_test_path, test_name)
|
||||
else:
|
||||
raise ValueError("Invalid test_screen option.")
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def client(request):
|
||||
"""Client fixture.
|
||||
@ -209,7 +92,6 @@ def client(request):
|
||||
|
||||
wipe_device(client)
|
||||
|
||||
# fmt: off
|
||||
setup_params = dict(
|
||||
uninitialized=False,
|
||||
mnemonic=" ".join(["all"] * 12),
|
||||
@ -219,7 +101,6 @@ def client(request):
|
||||
no_backup=False,
|
||||
random_seed=None,
|
||||
)
|
||||
# fmt: on
|
||||
|
||||
marker = request.node.get_closest_marker("setup_client")
|
||||
if marker:
|
||||
@ -251,7 +132,7 @@ def client(request):
|
||||
if setup_params["random_seed"] is not None:
|
||||
client.debug.reseed(setup_params["random_seed"])
|
||||
|
||||
with _screen_recording(client, request):
|
||||
with ui_tests.screen_recording(client, request):
|
||||
yield client
|
||||
|
||||
client.close()
|
||||
|
121
tests/ui_tests/__init__.py
Normal file
121
tests/ui_tests/__init__.py
Normal file
@ -0,0 +1,121 @@
|
||||
import hashlib
|
||||
import re
|
||||
import shutil
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from .html import create_diff_doc
|
||||
|
||||
|
||||
def _get_test_dirname(node):
|
||||
# This composes the dirname from the test module name and test item name.
|
||||
# Test item name is usually function name, but when parametrization is used,
|
||||
# parameters are also part of the name. Some functions have very long parameter
|
||||
# names (tx hashes etc) that run out of maximum allowable filename length, so
|
||||
# we limit the name to first 100 chars. This is not a problem with txhashes.
|
||||
node_name = re.sub(r"\W+", "_", node.name)[:100]
|
||||
node_module_name = node.getparent(pytest.Module).name
|
||||
return "{}_{}".format(node_module_name, node_name)
|
||||
|
||||
|
||||
def _check_fixture_directory(fixture_dir, screen_path):
|
||||
# create the fixture dir if it does not exist
|
||||
if not fixture_dir.exists():
|
||||
fixture_dir.mkdir()
|
||||
|
||||
# delete old files
|
||||
shutil.rmtree(screen_path, ignore_errors=True)
|
||||
screen_path.mkdir()
|
||||
|
||||
|
||||
def _process_recorded(screen_path):
|
||||
records = sorted(screen_path.iterdir())
|
||||
|
||||
# create hash
|
||||
digest = _hash_files(records)
|
||||
with open(screen_path / "../hash.txt", "w") as f:
|
||||
f.write(digest)
|
||||
_rename_records(screen_path)
|
||||
|
||||
|
||||
def _rename_records(screen_path):
|
||||
# rename screenshots
|
||||
for index, record in enumerate(sorted(screen_path.iterdir())):
|
||||
filename = screen_path / "{:08}.png".format(index)
|
||||
record.replace(filename)
|
||||
|
||||
|
||||
def _hash_files(files):
|
||||
hasher = hashlib.sha256()
|
||||
for file in sorted(files):
|
||||
with open(file, "rb") as f:
|
||||
content = f.read()
|
||||
hasher.update(content)
|
||||
|
||||
return hasher.digest().hex()
|
||||
|
||||
|
||||
def _process_tested(fixture_test_path, test_name):
|
||||
hash_file = fixture_test_path / "hash.txt"
|
||||
|
||||
if not hash_file.exists():
|
||||
raise ValueError("File hash.txt not found.")
|
||||
|
||||
with open(hash_file, "r") as f:
|
||||
expected_hash = f.read()
|
||||
|
||||
actual_path = fixture_test_path / "actual"
|
||||
_rename_records(actual_path)
|
||||
|
||||
records = sorted(actual_path.iterdir())
|
||||
actual_hash = _hash_files(records)
|
||||
|
||||
if actual_hash != expected_hash:
|
||||
create_diff_doc(fixture_test_path, test_name, actual_hash, expected_hash)
|
||||
pytest.fail(
|
||||
"Hash of {} differs.\nExpected: {}\nActual: {}".format(
|
||||
test_name, expected_hash, actual_hash
|
||||
)
|
||||
)
|
||||
else:
|
||||
if (fixture_test_path / "diff.html").exists():
|
||||
(fixture_test_path / "diff.html").unlink()
|
||||
|
||||
|
||||
@contextmanager
|
||||
def screen_recording(client, request):
|
||||
if not request.node.get_closest_marker("skip_ui"):
|
||||
test_screen = request.config.getoption("test_screen")
|
||||
else:
|
||||
test_screen = ""
|
||||
|
||||
if not test_screen:
|
||||
yield
|
||||
return
|
||||
|
||||
fixture_root = Path(__file__) / "../fixtures"
|
||||
test_name = _get_test_dirname(request.node)
|
||||
fixture_test_path = fixture_root.resolve() / test_name
|
||||
|
||||
if test_screen == "record":
|
||||
screen_path = fixture_test_path / "recorded"
|
||||
elif test_screen == "test":
|
||||
screen_path = fixture_test_path / "actual"
|
||||
else:
|
||||
raise ValueError("Invalid test_screen option.")
|
||||
|
||||
_check_fixture_directory(fixture_test_path, screen_path)
|
||||
|
||||
try:
|
||||
client.debug.start_recording(str(screen_path))
|
||||
yield
|
||||
finally:
|
||||
client.debug.stop_recording()
|
||||
if test_screen == "record":
|
||||
_process_recorded(screen_path)
|
||||
elif test_screen == "test":
|
||||
_process_tested(fixture_test_path, test_name)
|
||||
else:
|
||||
raise ValueError("Invalid test_screen option.")
|
Loading…
Reference in New Issue
Block a user