Quickstart First Run
mtv-api-tests uses pytest with pytest-testconfig. The shared test catalog is already wired into the repo, so a first run is mostly about three things:
- Create
.providers.jsonin the repository root. - Pass the environment-specific runtime values with
--tc=.... - Start with
--collect-onlyor--setup-plan, then run one small sanity class.
This page assumes you are running from the repository root with project dependencies already available.
How Configuration Works
pytest.ini already tells pytest to load tests/tests_config/config.py through pytest-testconfig:
[pytest]
testpaths = tests
addopts =
-s
-o log_cli=true
-p no:logging
--tc-file=tests/tests_config/config.py
--tc-format=python
--junit-xml=junit-report.xml
--basetemp=/tmp/pytest
--show-progress
--strict-markers
--jira
--dist=loadscope
For real test execution, the suite requires two runtime keys:
def pytest_sessionstart(session):
required_config = ("storage_class", "source_provider")
Note: You normally do not need to pass
--tc-fileyourself. The repo already points pytest attests/tests_config/config.py, so the usual workflow is to add runtime overrides with--tc=key:value.
Create .providers.json
The provider loader looks for .providers.json in the current working directory and parses it as JSON:
def load_source_providers() -> dict[str, dict[str, Any]]:
providers_file = Path(".providers.json")
if not providers_file.exists():
return {}
with open(providers_file) as fd:
content = fd.read()
if not content.strip():
return {}
return json.loads(content)
Create .providers.json in the repository root. Use .providers.json.example as the starting template. This is the vSphere block from that file:
"vsphere": {
"type": "vsphere",
"version": "<SERVER VERSION>",
"fqdn": "SERVER FQDN/IP",
"api_url": "<SERVER FQDN/IP>/sdk",
"username": "USERNAME",
"password": "PASSWORD", # pragma: allowlist secret
"guest_vm_linux_user": "LINUX VMS USERNAME",
"guest_vm_linux_password": "LINUX VMS PASSWORD", # pragma: allowlist secret
"guest_vm_win_user": "WINDOWS VMS USERNAME",
"guest_vm_win_password": "WINDOWS VMS PASSWORD", # pragma: allowlist secret
"vddk_init_image": "<PATH TO VDDK INIT IMAGE>"
}
The same example file also includes templates for ovirt, openstack, openshift, and ova.
Warning:
.providers.json.exampleis not valid JSON as-is. It contains comments and placeholder values. Your real.providers.jsonmust be valid JSON, because the loader usesjson.loads(...).Note: The top-level provider key is what you pass later as
--tc=source_provider:<key>. If your file uses"vsphere", then your runtime flag must use--tc=source_provider:vsphere.Warning:
.providers.jsoncontains credentials. Keep it local and treat it as sensitive.
Know What the Built-In Plans Expect
The shared defaults and named test plans live in tests/tests_config/config.py. These are the defaults most relevant to a first run:
insecure_verify_skip: str = "true"
source_provider_insecure_skip_verify: str = "false"
target_namespace_prefix: str = "auto"
mtv_namespace: str = "openshift-mtv"
remote_ocp_cluster: str = ""
plan_wait_timeout: int = 3600
For a first targeted migration, the smallest built-in cold plan is:
"test_sanity_cold_mtv_migration": {
"virtual_machines": [
{"name": "mtv-tests-rhel8", "guest_agent": True},
],
"warm_migration": False,
},
The warm equivalent is:
"test_sanity_warm_mtv_migration": {
"virtual_machines": [
{
"name": "mtv-tests-rhel8",
"source_vm_power": "on",
"guest_agent": True,
},
],
"warm_migration": True,
},
Tip: If you want the smoothest first run, prepare a source VM named
mtv-tests-rhel8and start with the cold sanity plan. If your lab uses different VM names, update the matching entry intests/tests_config/config.pybefore your first real run.
Pass Runtime Settings With pytest-testconfig
For a first run, these are the settings you will usually care about:
source_provider: required for real execution; must match a top-level key in.providers.jsonstorage_class: required for real execution; destination OpenShift storage classcluster_host,cluster_username,cluster_password: useful when you want to pass OpenShift access explicitly on the command linemtv_namespace: optional; defaults toopenshift-mtvtarget_namespace_prefix: optional; defaults toautoinsecure_verify_skip: optional; controls OpenShift API TLS verificationsource_provider_insecure_skip_verify: optional; controls source-provider TLS verification
A typical first-run command shape is:
uv run pytest -v tests/test_mtv_cold_migration.py::TestSanityColdMtvMigration \
--tc=source_provider:vsphere \
--tc=storage_class:<storage-class> \
--tc=cluster_host:https://api.<cluster>:6443 \
--tc=cluster_username:<username> \
--tc=cluster_password:${CLUSTER_PASSWORD}
If your provider key is not vsphere, replace it with the top-level key you actually used in .providers.json.
If you need to relax source-provider TLS verification in a lab environment, add:
--tc=source_provider_insecure_skip_verify:true
If your MTV operator is not installed in openshift-mtv, add:
--tc=mtv_namespace:<your-mtv-namespace>
Start With --collect-only Or --setup-plan
This repo treats both --collect-only and --setup-plan as normal dry-run entry points. In fact, tox.toml uses both as a basic pytest check, and the container image in Dockerfile defaults to uv run pytest --collect-only.
Use --collect-only when you want to confirm what pytest will select:
uv run pytest --collect-only -q tests/test_mtv_cold_migration.py::TestSanityColdMtvMigration
Use --setup-plan when you want to see fixture/setup planning for the same target before a real run:
uv run pytest --setup-plan tests/test_mtv_cold_migration.py::TestSanityColdMtvMigration \
--tc=source_provider:vsphere \
--tc=storage_class:<storage-class>
If you want to browse by marker first, the built-in markers are:
tier0warmremotecopyoffload
For example, to list the smoke-suite tests:
uv run pytest --collect-only -q -m tier0
Tip:
--collect-onlyis the safest place to start when you want to confirm test names, markers, and node IDs before wiring in all runtime values.
Run The First Targeted Test Class
The cold sanity test is defined in tests/test_mtv_cold_migration.py like this:
@pytest.mark.tier0
@pytest.mark.incremental
@pytest.mark.parametrize(
"class_plan_config",
[
pytest.param(
py_config["tests_params"]["test_sanity_cold_mtv_migration"],
)
],
indirect=True,
ids=["rhel8"],
)
@pytest.mark.usefixtures("cleanup_migrated_vms")
class TestSanityColdMtvMigration:
"""Cold migration test - sanity check."""
That class runs the migration as five dependent steps:
test_create_storagemaptest_create_networkmaptest_create_plantest_migrate_vmstest_check_vms
Run the whole class, not a single method:
uv run pytest -v tests/test_mtv_cold_migration.py::TestSanityColdMtvMigration \
--tc=source_provider:vsphere \
--tc=storage_class:<storage-class> \
--tc=cluster_host:https://api.<cluster>:6443 \
--tc=cluster_username:<username> \
--tc=cluster_password:${CLUSTER_PASSWORD}
If you specifically want to try the warm sanity path afterward, use:
uv run pytest -v tests/test_mtv_warm_migration.py::TestSanityWarmMtvMigration \
--tc=source_provider:vsphere \
--tc=storage_class:<storage-class> \
--tc=cluster_host:https://api.<cluster>:6443 \
--tc=cluster_username:<username> \
--tc=cluster_password:${CLUSTER_PASSWORD}
Warning: Warm tests are explicitly skipped in this repo for
openstack,openshift, andovaproviders. For a first run, the cold sanity class is the safer starting point.
Common First-Run Problems
If the run fails early, check these first:
.providers.jsonis missing or empty.- The value passed in
--tc=source_provider:...does not exactly match a top-level key in.providers.json. .providers.jsonwas copied from.providers.json.examplewithout removing comments.- The built-in sanity plan expects a source VM named
mtv-tests-rhel8, but that VM does not exist in your provider. - You targeted a single method such as
::test_create_planinstead of the full class. - You chose a warm test on a provider type that the repo skips for warm migration.
Tip: By default, the suite writes
junit-report.xmland tears down created resources after the run. If you need to inspect what was created after a failure, rerun with--skip-teardown.