You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Tests/samples/sample_tests.py

164 lines
7.6 KiB
Python

"""
All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
its licensors.
For complete copyright and license terms please see the LICENSE at the root of this
distribution (the "License"). All use of this software is governed by the License,
or, if provided, by the license below or the license accompanying this file. Do not
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Sample tests to demonstrate typical functionality of PythonTestTools and how to integrate into the BAT.
"""
# Workaround for tests which depend on old tools, before they are updated to ly_test_tools and Python 3
import pytest
pytest.importorskip('test_tools')
# System level imports
import os
import subprocess
# Basic PythonTestTools imports, in most cases you should always import these
import test_tools.builtin.fixtures as fixtures
from test_tools import HOST_PLATFORM, WINDOWS_LAUNCHER
# test_tools and shared are modules with a lot of useful utility functions already written, use them!
# Pick and choose the ones below that you need, don't just blindly copy/paste
import test_tools.launchers.phase
import test_tools.shared.process_utils as process_utils
from test_tools.shared.file_utils import gather_error_logs, clear_out_config_file, delete_screenshot_folder, move_file
from shared.network_utils import check_for_listening_port
from test_tools.shared.remote_console_commands import RemoteConsole
from test_tools.shared.waiter import wait_for
# This is where you should access lumberyard - building, asset processing, finding paths/logs, etc. Do NOT change or
# remove this unless you know what you're doing.
# See the documentation for PythonTestTools for more information.
workspace = fixtures.use_fixture(fixtures.builtin_empty_workspace_fixture, scope='function')
# What are fixtures?
# Fixtures set up a testing process (or test) by running all necessary code to satisfy its preconditions.
# More reading here: https://docs.pytest.org/en/latest/fixture.html
# This is a shared instance of the remote console that be used across multiple tests. It must have the @pytest.fixture!
# You should remove this if you aren't going to use the remote console.
@pytest.fixture
def remote_console_instance(request):
"""
Creates a remote console instance to send console commands.
"""
console = RemoteConsole()
def teardown():
try:
console.stop()
except:
pass
request.addfinalizer(teardown)
return console
# This is a shared instance of the launcher that can be used across multiple tests within this file and any that it
# includes. It must have the @pytest.fixture for pytest to automatically pass it around!
# You should remove this if you aren't going to use the level-specific launchers.
@pytest.fixture
def launcher_instance(request, workspace, level):
"""
Creates a launcher fixture instance with an extra teardown for error log grabbing.
"""
def teardown_launcher_copy_logs():
"""
Tries to grab any error logs before moving on to the next test.
"""
for file_name in os.listdir(launcher.workspace.release.paths.project_log()):
move_file(launcher.workspace.release.paths.project_log(),
launcher.workspace.artifact_manager.get_save_artifact_path(),
file_name)
logs_exist = lambda: gather_error_logs(
launcher.workspace.release.paths.dev(),
launcher.workspace.artifact_manager.get_save_artifact_path())
try:
test_tools.shared.waiter.wait_for(logs_exist)
except AssertionError:
print("No error logs found. Completing test...")
request.addfinalizer(teardown_launcher_copy_logs)
launcher = fixtures.launcher(request, workspace, level)
return launcher
# For the rest of the file, these are sample tests that you should remove entirely, or cannibalize them to help your
# own test-writing process.
class TestSamplesAPBatch:
# This is a shared instance of test teardown that will be used across all tests in this class.
# It must have the @pytest.fixture(autouse=True)!
@pytest.fixture(autouse=True)
def setup_teardown(self, request):
# This is the teardown function that will be run after *each* test finishes
def teardown():
pass
# This is the setup section that will be run before *each* test starts
request.addfinalizer(teardown)
# mark.BAT adds this test to the BAT.
# mark.test_case is used to link to your testrail id.
# mark.parameterize allows you to run the same test multiple times but with different parameters, such as platform,
# configuration, project, level, and more. See more on parameters here: https://docs.pytest.org/en/latest/parametrize.html
@pytest.mark.BAT
@pytest.mark.test_case(testrail_id='Foo')
@pytest.mark.parametrize('platform,configuration,project,spec', (
pytest.param('win_x64_vs2017', 'profile', 'StarterGame', 'all',
marks=pytest.mark.skipif(HOST_PLATFORM != 'win_x64', reason='Only supported on Windows hosts')),
pytest.param('darwin_x64', 'profile', 'StarterGame', 'all',
marks=pytest.mark.skipif(HOST_PLATFORM != 'darwin_x64', reason='Only supported on Mac hosts')),
))
def test_RunAPBatch_WorkspacePreconfigured_NoLeftoverProcessesExist(self, workspace):
"""
Tests that the Asset Processor Batch and run and doesn't leave leftover processes.
"""
# Your function docstrings (the above text) will be part of the test catalog!
subprocess.check_call([os.path.join(workspace.release.paths.bin(), 'AssetProcessorBatch')])
# This is how you should do timeouts
wait_for(lambda: not process_utils.process_exists('AssetProcessorBatch', True), timeout=10)
# Make sure to include an informative assert message to make debugging easier
assert not process_utils.process_exists('rc', True), 'rc process still exists'
assert not process_utils.process_exists('AssetBuilder', True), 'AssetBuilder process still exists'
# Notice that you can put the marks both on the class and on the individual methods (seen above).
@pytest.mark.BAT
@pytest.mark.parametrize("platform,configuration,project,spec,level", [
pytest.param("win_x64_vs2017", "profile", "StarterGame", "all", "StarterGame",
marks=pytest.mark.skipif(not WINDOWS_LAUNCHER, reason="Only supported on Windows hosts")),
pytest.param("win_x64_vs2019", "profile", "StarterGame", "all", "StarterGame",
marks=pytest.mark.skipif(not WINDOWS_LAUNCHER, reason="Only supported on Windows hosts"))
])
class TestSamplesRemoteConsole(object):
# Notice here that both the launcher_instance and remote_console_instance fixtures are being reused from above
def test_LaunchRemoteConsoleAndLauncher_CanLaunch(self, launcher_instance, platform, configuration, project, spec,
level, remote_console_instance):
"""
Verifies launcher & remote console can successfully launch. Notice that there are no asserts here, and that is
because the called functions will raise exceptions if there is unexpected behavior.
"""
launcher_instance.launch()
launcher_instance.run(test_tools.launchers.phase.TimePhase(120, 120))
test_tools.shared.waiter.wait_for(lambda: check_for_listening_port(4600), timeout=300,
exc=AssertionError('Port 4600 not listening.'))
remote_console_instance.start()