Load tests dynamically + Parameterize the test pipeline (#2745)

* Load tests dynamically + Parameterize the test pipeline
This commit is contained in:
Norberto Arrieta 2023-01-30 14:24:04 -08:00 коммит произвёл GitHub
Родитель 8328286872
Коммит 629a0eced7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
18 изменённых файлов: 460 добавлений и 211 удалений

Просмотреть файл

@ -0,0 +1,107 @@
# Microsoft Azure Linux Agent
#
# Copyright 2018 Microsoft Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import importlib.util
import json
from pathlib import Path
from typing import Any, Dict, List, Type
from tests_e2e.scenarios.lib.agent_test import AgentTest
class TestSuiteDescription(object):
"""
Description of the test suite loaded from its JSON file.
"""
name: str
tests: List[Type[AgentTest]]
class AgentTestLoader(object):
"""
Loads the description of a set of test suites
"""
def __init__(self, test_source_directory: Path):
"""
The test_source_directory parameter must be the root directory of the end-to-end tests (".../WALinuxAgent/tests_e2e")
"""
self._root: Path = test_source_directory/"scenarios"
def load(self, test_suites: str) -> List[TestSuiteDescription]:
"""
Loads the specified 'test_suites', which are given as a string of comma-separated suite names or a JSON description
of a single test_suite.
When given as a comma-separated list, each item must correspond to the name of the JSON files describing s suite (those
files are located under the .../WALinuxAgent/tests_e2e/scenarios/testsuites directory). For example,
if test_suites == "agent_bvt, fast-track" then this method will load files agent_bvt.json and fast-track.json.
When given as a JSON string, the value must correspond to the description a single test suite, for example
{
"name": "AgentBvt",
"tests": [
"bvts/extension_operations.py",
"bvts/run_command.py",
"bvts/vm_access.py"
]
}
"""
# Attempt to parse 'test_suites' as the JSON description for a single suite
try:
return [self._load_test_suite(json.loads(test_suites))]
except json.decoder.JSONDecodeError:
pass
# Else, it should be a comma-separated list of description files
description_files: List[Path] = [self._root/"testsuites"/f"{t.strip()}.json" for t in test_suites.split(',')]
return [self._load_test_suite(AgentTestLoader._load_file(s)) for s in description_files]
def _load_test_suite(self, test_suite: Dict[str, Any]) -> TestSuiteDescription:
"""
Creates a TestSuiteDescription from its JSON representation, which has been loaded by JSON.loads and is passed
to this method as a dictionary
"""
suite = TestSuiteDescription()
suite.name = test_suite["name"]
suite.tests = []
for source_file in [self._root/"tests"/t for t in test_suite["tests"]]:
suite.tests.extend(AgentTestLoader._load_tests(source_file))
return suite
@staticmethod
def _load_tests(source_file: Path) -> List[Type[AgentTest]]:
"""
Takes a 'source_file', which must be a Python module, and returns a list of all the classes derived from AgentTest.
"""
spec = importlib.util.spec_from_file_location(f"tests_e2e.scenarios.{source_file.name}", str(source_file))
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
# return all the classes in the module that are subclasses of AgentTest but are not AgentTest itself.
return [v for v in module.__dict__.values() if isinstance(v, type) and issubclass(v, AgentTest) and v != AgentTest]
@staticmethod
def _load_file(file: Path):
"""Helper to load a JSON file"""
try:
with file.open() as f:
return json.load(f)
except Exception as e:
raise Exception(f"Can't load {file}: {e}")

Просмотреть файл

@ -14,13 +14,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import contextlib
import logging
import re
from assertpy import fail
from enum import Enum
from pathlib import Path
from threading import current_thread, RLock
from typing import List, Type
from typing import Any, Dict, List
# Disable those warnings, since 'lisa' is an external, non-standard, dependency
# E0401: Unable to import 'lisa' (import-error)
@ -31,17 +33,19 @@ from lisa import ( # pylint: disable=E0401
Logger,
Node,
TestSuite,
TestSuiteMetadata
TestSuiteMetadata,
TestCaseMetadata,
)
from lisa.sut_orchestrator import AZURE # pylint: disable=E0401
from lisa.sut_orchestrator.azure.common import get_node_context, AzureNodeSchema # pylint: disable=E0401
import makepkg
from azurelinuxagent.common.version import AGENT_VERSION
from tests_e2e.scenarios.lib.agent_test import AgentTest
from tests_e2e.orchestrator.lib.agent_test_loader import AgentTestLoader, TestSuiteDescription
from tests_e2e.scenarios.lib.agent_test_context import AgentTestContext
from tests_e2e.scenarios.lib.identifiers import VmIdentifier
from tests_e2e.scenarios.lib.logging import log as agent_test_logger # Logger used by the tests
from tests_e2e.scenarios.lib.logging import set_current_thread_log
def _initialize_lisa_logger():
@ -68,6 +72,29 @@ def _initialize_lisa_logger():
_initialize_lisa_logger()
#
# Helper to change the current thread name temporarily
#
@contextlib.contextmanager
def _set_thread_name(name: str):
initial_name = current_thread().name
current_thread().name = name
try:
yield
finally:
current_thread().name = initial_name
#
# Possible values for the collect_logs parameter
#
class CollectLogs(Enum):
Always = 'always' # Always collect logs
Failed = 'failed' # Collect logs only on test failures
No = 'no' # Never collect logs
@TestSuiteMetadata(area="waagent", category="", description="")
class AgentTestSuite(TestSuite):
"""
Base class for Agent test suites. It provides facilities for setup, execution of tests and reporting results. Derived
@ -81,14 +108,17 @@ class AgentTestSuite(TestSuite):
self.log: Logger = None
self.node: Node = None
self.runbook_name: str = None
self.suite_name: str = None
self.image_name: str = None
self.test_suites: List[str] = None
self.collect_logs: str = None
self.skip_setup: bool = None
def __init__(self, metadata: TestSuiteMetadata) -> None:
super().__init__(metadata)
# The context is initialized by _set_context() via the call to execute()
self.__context: AgentTestSuite._Context = None
def _set_context(self, node: Node, log: Logger):
def _set_context(self, node: Node, variables: Dict[str, Any], log: Logger):
connection_info = node.connection_info
node_context = get_node_context(node)
runbook = node.capability.get_extended_runbook(AzureNodeSchema, AZURE)
@ -113,7 +143,23 @@ class AgentTestSuite(TestSuite):
self.__context.log = log
self.__context.node = node
self.__context.suite_name = f"{self._metadata.full_name}_{runbook.marketplace.offer}-{runbook.marketplace.sku}"
self.__context.image_name = f"{runbook.marketplace.offer}-{runbook.marketplace.sku}"
self.__context.test_suites = AgentTestSuite._get_required_parameter(variables, "test_suites")
self.__context.collect_logs = AgentTestSuite._get_required_parameter(variables, "collect_logs")
self.__context.skip_setup = AgentTestSuite._get_required_parameter(variables, "skip_setup")
self._log.info(
"Test suite parameters: [skip_setup: %s] [collect_logs: %s] [test_suites: %s]",
self.context.skip_setup,
self.context.collect_logs,
self.context.test_suites)
@staticmethod
def _get_required_parameter(variables: Dict[str, Any], name: str) -> Any:
value = variables.get(name)
if value is None:
raise Exception(f"The runbook is missing required parameter '{name}'")
return value
@property
def context(self):
@ -234,94 +280,103 @@ class AgentTestSuite(TestSuite):
# Copy the tarball to the local logs directory
remote_path = "/tmp/waagent-logs.tgz"
local_path = Path.home()/'logs'/'{0}.tgz'.format(self.context.suite_name)
local_path = Path.home()/'logs'/'{0}.tgz'.format(self.context.image_name)
self._log.info("Copying %s:%s to %s", self.context.node.name, remote_path, local_path)
self.context.node.shell.copy_back(remote_path, local_path)
except: # pylint: disable=bare-except
self._log.exception("Failed to collect logs from the test machine")
def execute(self, node: Node, log: Logger, test_suite: List[Type[AgentTest]]) -> None:
@TestCaseMetadata(description="", priority=0)
def execute(self, node: Node, variables: Dict[str, Any], log: Logger) -> None:
"""
Executes each of the AgentTests in the given List. Note that 'test_suite' is a list of test classes, rather than
instances of the test class (this method will instantiate each of these test classes).
"""
self._set_context(node, log)
self._set_context(node, variables, log)
failed: List[str] = [] # List of failed tests (names only)
# The thread name is added to self._log, set it to the current test suite while we execute it
thread_name = current_thread().name
current_thread().name = self.context.suite_name
# We create a separate log file for the test suite.
suite_log_file: Path = Path.home()/'logs'/f"{self.context.suite_name}.log"
agent_test_logger.set_current_thread_log(suite_log_file)
try:
self._setup()
with _set_thread_name(self.context.image_name): # The thread name is added to self._log
try:
self._setup_node()
if not self.context.skip_setup:
self._setup()
agent_test_logger.info("")
agent_test_logger.info("**************************************** %s ****************************************", self.context.suite_name)
agent_test_logger.info("")
try:
if not self.context.skip_setup:
self._setup_node()
results: List[str] = []
test_suites: List[TestSuiteDescription] = AgentTestLoader(self.context.test_source_directory).load(self.context.test_suites)
for test in test_suite:
result: str = "[UNKNOWN]"
test_full_name = f"{self.context.suite_name} {test.__name__}"
agent_test_logger.info("******** Executing %s", test_full_name)
self._log.info("******** Executing %s", test_full_name)
agent_test_logger.info("")
for suite in test_suites:
failed.extend(self._execute_test_suite(suite))
try:
test(self.context).run()
result = f"[Passed] {test_full_name}"
except AssertionError as e:
failed.append(test.__name__)
result = f"[Failed] {test_full_name}"
agent_test_logger.error("%s", e)
self._log.error("%s", e)
except: # pylint: disable=bare-except
failed.append(test.__name__)
result = f"[Error] {test_full_name}"
agent_test_logger.exception("UNHANDLED EXCEPTION IN %s", test_full_name)
self._log.exception("UNHANDLED EXCEPTION IN %s", test_full_name)
finally:
collect = self.context.collect_logs
if collect == CollectLogs.Always or collect == CollectLogs.Failed and len(failed) > 0:
self._collect_node_logs()
agent_test_logger.info("******** %s", result)
agent_test_logger.info("")
self._log.info("******** %s", result)
results.append(result)
agent_test_logger.info("")
agent_test_logger.info("********* [Test Results]")
agent_test_logger.info("")
for r in results:
agent_test_logger.info("\t%s", r)
agent_test_logger.info("")
except: # pylint: disable=bare-except
# Note that we report the error to the LISA log and then re-raise it. We log it here
# so that the message is decorated with the thread name in the LISA log; we re-raise
# to let LISA know the test errored out (LISA will report that error one more time
# in its log)
self._log.exception("UNHANDLED EXCEPTION")
raise
finally:
self._collect_node_logs()
except: # pylint: disable=bare-except
agent_test_logger.exception("UNHANDLED EXCEPTION IN %s", self.context.suite_name)
# Note that we report the error to the LISA log and then re-raise it. We log it here
# so that the message is decorated with the thread name in the LISA log; we re-raise
# to let LISA know the test errored out (LISA will report that error one more time
# in its log)
self._log.exception("UNHANDLED EXCEPTION IN %s", self.context.suite_name)
raise
finally:
self._clean_up()
agent_test_logger.close_current_thread_log()
current_thread().name = thread_name
self._clean_up()
# Fail the entire test suite if any test failed; this exception is handled by LISA
if len(failed) > 0:
fail(f"{[self.context.suite_name]} One or more tests failed: {failed}")
fail(f"{[self.context.image_name]} One or more tests failed: {failed}")
def _execute_test_suite(self, suite: TestSuiteDescription) -> List[str]:
suite_name = suite.name
suite_full_name = f"{suite_name}-{self.context.image_name}"
with _set_thread_name(suite_full_name): # The thread name is added to self._log
with set_current_thread_log(Path.home()/'logs'/f"{suite_full_name}.log"):
agent_test_logger.info("")
agent_test_logger.info("**************************************** %s ****************************************", suite_name)
agent_test_logger.info("")
failed: List[str] = []
summary: List[str] = []
for test in suite.tests:
test_name = test.__name__
test_full_name = f"{suite_name}-{test_name}"
agent_test_logger.info("******** Executing %s", test_name)
self._log.info("******** Executing %s", test_full_name)
try:
test(self.context).run()
summary.append(f"[Passed] {test_name}")
agent_test_logger.info("******** [Passed] %s", test_name)
self._log.info("******** [Passed] %s", test_full_name)
except AssertionError as e:
summary.append(f"[Failed] {test_name}")
failed.append(test_full_name)
agent_test_logger.error("******** [Failed] %s: %s", test_name, e)
self._log.error("******** [Failed] %s", test_full_name)
except: # pylint: disable=bare-except
summary.append(f"[Error] {test_name}")
failed.append(test_full_name)
agent_test_logger.exception("UNHANDLED EXCEPTION IN %s", test_name)
self._log.exception("UNHANDLED EXCEPTION IN %s", test_full_name)
agent_test_logger.info("")
agent_test_logger.info("********* [Test Results]")
agent_test_logger.info("")
for r in summary:
agent_test_logger.info("\t%s", r)
agent_test_logger.info("")
return failed
def execute_script_on_node(self, script_path: Path, parameters: str = "", sudo: bool = False) -> int:
"""

Просмотреть файл

@ -1,11 +1,11 @@
name: Daily
name: WALinuxAgent
testcase:
- criteria:
area: bvt
area: waagent
extension:
- "../testsuites"
- "./lib"
variable:
- name: subscription_id
@ -23,7 +23,22 @@ variable:
value: ""
is_secret: true
#
# Set these to use an SSH proxy
#
- name: proxy
value: False
- name: proxy_host
value: ""
- name: proxy_user
value: "foo"
- name: proxy_identity_file
value: ""
is_secret: true
#
# The image, vm_size, and location are set by the combinator
#
- name: marketplace_image
value: ""
- name: vm_size
@ -33,6 +48,25 @@ variable:
- name: default_location
value: "westus2"
#
# These variables define parameters for the AgentTestSuite; see the test wiki for details
#
# The test suites to execute
- name: test_suites
value: "agent_bvt"
is_case_visible: true
# Whether to collect logs from the test VM
- name: collect_logs
value: "failed"
is_case_visible: true
# Whether to skip setup of the test VM
- name: skip_setup
value: false
is_case_visible: true
platform:
- type: azure
admin_username: $(user)
@ -85,6 +119,12 @@ concurrency: 10
notifier:
- type: agent.junit
include:
- path: ./include/ssh_proxy.yml
dev:
enabled: $(proxy)
mock_tcp_ping: $(proxy)
jump_boxes:
- private_key_file: $(proxy_identity_file)
address: $(proxy_host)
username: $(proxy_user)
password: "dummy"

Просмотреть файл

@ -22,10 +22,10 @@ name: ExistingVM
testcase:
- criteria:
area: bvt
area: waagent
extension:
- "../../testsuites"
- "../lib"
variable:
- name: subscription_id
@ -44,6 +44,30 @@ variable:
value: ""
is_secret: true
# Set these to use an SSH proxy
- name: proxy
value: False
- name: proxy_host
value: ""
- name: proxy_user
value: "foo"
- name: proxy_identity_file
value: ""
is_secret: true
# These variables define parameters for the AgentTestSuite
- name: test_suites
value: "agent_bvt"
is_case_visible: true
- name: collect_logs
value: "failed"
is_case_visible: true
- name: skip_setup
value: true
is_case_visible: true
platform:
- type: azure
admin_username: $(user)
@ -61,5 +85,11 @@ notifier:
- type: env_stats
- type: agent.junit
include:
- path: ../include/ssh_proxy.yml
dev:
enabled: $(proxy)
mock_tcp_ping: $(proxy)
jump_boxes:
- private_key_file: $(proxy_identity_file)
address: $(proxy_host)
username: $(proxy_user)
password: "dummy"

Просмотреть файл

@ -22,18 +22,52 @@
# to manage the test VMs taking the initial key value from the file shared by the container host, then it
# executes the daily test runbook.
#
# TODO: The runbook should be parameterized.
#
set -euxo pipefail
cd "$HOME"
usage() (
echo "Usage: run-scenarios [-t|--test-suites <test suites>] [-l|--collect-logs <always|failed|no>] [-k|--skip-setup <True|False>]"
exit 1
)
test_suite_parameters=""
while [[ $# -gt 0 ]]
do
case $1 in
-t|--test-suites)
shift
if [ "$#" -lt 1 ]; then
usage
fi
test_suite_parameters="$test_suite_parameters -v test_suites:$1"
;;
-l|--collect-logs)
shift
if [ "$#" -lt 1 ]; then
usage
fi
test_suite_parameters="$test_suite_parameters -v collect_logs:$1"
;;
-k|--skip-setup)
shift
if [ "$#" -lt 1 ]; then
usage
fi
test_suite_parameters="$test_suite_parameters -v skip_setup:$1"
;;
*)
usage
esac
shift
done
# The private ssh key is shared from the container host as $HOME/id_rsa; copy it to
# HOME/.ssh, set the correct mode and generate the public key.
mkdir "$HOME/.ssh"
cp "$HOME/id_rsa" "$HOME/.ssh"
chmod 700 "$HOME/.ssh/id_rsa"
ssh-keygen -y -f "$HOME/.ssh/id_rsa" > "$HOME/.ssh/id_rsa.pub"
# $HOME/.ssh, set the correct mode and generate the public key.
cd "$HOME"
mkdir .ssh
cp id_rsa .ssh
chmod 700 .ssh/id_rsa
ssh-keygen -y -f .ssh/id_rsa > .ssh/id_rsa.pub
#
# Now start the runbook
@ -41,9 +75,9 @@ ssh-keygen -y -f "$HOME/.ssh/id_rsa" > "$HOME/.ssh/id_rsa.pub"
lisa_logs="$HOME/logs/lisa"
lisa \
--runbook "$HOME/WALinuxAgent/tests_e2e/scenarios/runbooks/daily.yml" \
--runbook "$HOME/WALinuxAgent/tests_e2e/orchestrator/runbook.yml" \
--log_path "$lisa_logs" \
--working_path "$lisa_logs" \
-v subscription_id:"$SUBSCRIPTION_ID" \
-v identity_file:"$HOME/.ssh/id_rsa"
-v identity_file:"$HOME/.ssh/id_rsa" \
$test_suite_parameters

Просмотреть файл

@ -1,6 +1,33 @@
parameters:
# see the test wiki for a description of the parameters
- name: test_suites
displayName: Test Suites
type: string
default: agent_bvt
- name: collect_logs
displayName: Collect logs from test VMs
type: string
default: failed
values:
- always
- failed
- no
- name: skip_setup
displayName: Skip setup of the test VMs
type: boolean
default: false
variables:
- name: azureConnection
value: 'azuremanagement'
- name: test_suites
value: ${{ parameters.test_suites }}
- name: collect_logs
value: ${{ parameters.collect_logs }}
- name: skip_setup
value: ${{ parameters.skip_setup }}
trigger:
- develop
@ -10,9 +37,50 @@ pr: none
pool:
vmImage: ubuntu-latest
stages:
- stage: "ExecuteTests"
jobs:
- job: "ExecuteTests"
jobs:
- template: 'templates/execute-tests.yml'
steps:
- task: DownloadSecureFile@1
name: downloadSshKey
displayName: "Download SSH key"
inputs:
secureFile: 'id_rsa'
- task: AzureKeyVault@2
displayName: "Fetch secrets from KV"
inputs:
azureSubscription: '$(azureConnection)'
KeyVaultName: 'dcrV2SPs'
SecretsFilter: '*'
RunAsPreJob: true
- task: UsePythonVersion@0
displayName: "Set Python Version"
inputs:
versionSpec: '3.10'
addToPath: true
architecture: 'x64'
- bash: $(Build.SourcesDirectory)/tests_e2e/pipeline/scripts/execute_tests.sh
displayName: "Execute tests"
continueOnError: true
env:
# Add all KeyVault secrets explicitly as they're not added by default to the environment vars
AZURE_CLIENT_ID: $(AZURE-CLIENT-ID)
AZURE_CLIENT_SECRET: $(AZURE-CLIENT-SECRET)
AZURE_TENANT_ID: $(AZURE-TENANT-ID)
SUBSCRIPTION_ID: $(SUBSCRIPTION-ID)
- publish: $(Build.ArtifactStagingDirectory)
artifact: 'artifacts'
displayName: 'Publish test artifacts'
- task: PublishTestResults@2
displayName: 'Publish test results'
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: 'lisa/agent.junit.xml'
searchFolder: $(Build.ArtifactStagingDirectory)
failTaskOnFailedTests: true

Просмотреть файл

@ -27,7 +27,8 @@ docker run --rm \
--env AZURE_CLIENT_SECRET \
--env AZURE_TENANT_ID \
waagenttests.azurecr.io/waagenttests \
bash --login -c '$HOME/WALinuxAgent/tests_e2e/orchestrator/scripts/run-scenarios' \
bash --login -c \
"\$HOME/WALinuxAgent/tests_e2e/orchestrator/scripts/run-scenarios -t $TEST_SUITES -l $COLLECT_LOGS -k $SKIP_SETUP" \
|| echo "exit $?" > /tmp/exit.sh
# Retake ownership of the source and staging directory (note that the former does not need to be done recursively)

Просмотреть файл

@ -1,48 +0,0 @@
jobs:
- job: "ExecuteTests"
steps:
- task: DownloadSecureFile@1
name: downloadSshKey
displayName: "Download SSH key"
inputs:
secureFile: 'id_rsa'
- task: AzureKeyVault@2
displayName: "Fetch secrets from KV"
inputs:
azureSubscription: '$(azureConnection)'
KeyVaultName: 'dcrV2SPs'
SecretsFilter: '*'
RunAsPreJob: true
- task: UsePythonVersion@0
displayName: "Set Python Version"
inputs:
versionSpec: '3.10'
addToPath: true
architecture: 'x64'
- bash: $(Build.SourcesDirectory)/tests_e2e/pipeline/scripts/execute_tests.sh
displayName: "Execute tests"
continueOnError: true
env:
# Add all KeyVault secrets explicitly as they're not added by default to the environment vars
AZURE_CLIENT_ID: $(AZURE-CLIENT-ID)
AZURE_CLIENT_SECRET: $(AZURE-CLIENT-SECRET)
AZURE_TENANT_ID: $(AZURE-TENANT-ID)
SUBSCRIPTION_ID: $(SUBSCRIPTION-ID)
- publish: $(Build.ArtifactStagingDirectory)
artifact: 'artifacts'
displayName: 'Publish test artifacts'
- task: PublishTestResults@2
displayName: 'Publish test results'
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: 'lisa/agent.junit.xml'
searchFolder: $(Build.ArtifactStagingDirectory)
failTaskOnFailedTests: true

Просмотреть файл

@ -19,7 +19,7 @@
# This module defines a single object, 'log', of type AgentLogger, which the end-to-end tests and libraries use
# for logging.
#
import contextlib
from logging import FileHandler, Formatter, Handler, Logger, StreamHandler, INFO
from pathlib import Path
from threading import current_thread
@ -121,3 +121,14 @@ class AgentLogger(Logger):
log: AgentLogger = AgentLogger()
@contextlib.contextmanager
def set_current_thread_log(log_file: Path):
"""
Context Manager to set the log file for the current thread temporarily
"""
log.set_current_thread_log(log_file)
try:
yield
finally:
log.close_current_thread_log()

Просмотреть файл

@ -1,19 +0,0 @@
variable:
- name: proxy
value: False
- name: proxy_host
value: ""
- name: proxy_user
value: "foo"
- name: proxy_identity_file
value: ""
is_secret: true
dev:
enabled: $(proxy)
mock_tcp_ping: $(proxy)
jump_boxes:
- private_key_file: $(proxy_identity_file)
address: $(proxy_host)
username: $(proxy_user)
password: "dummy"

Просмотреть файл

Просмотреть файл

@ -0,0 +1,9 @@
{
"name": "AgentBvt",
"tests": [
"bvts/extension_operations.py",
"bvts/run_command.py",
"bvts/vm_access.py"
]
}

Просмотреть файл

@ -1,47 +0,0 @@
# Microsoft Azure Linux Agent
#
# Copyright 2018 Microsoft Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
from tests_e2e.orchestrator.lib.agent_test_suite import AgentTestSuite
from tests_e2e.scenarios.tests.bvts.extension_operations import ExtensionOperationsBvt
from tests_e2e.scenarios.tests.bvts.vm_access import VmAccessBvt
from tests_e2e.scenarios.tests.bvts.run_command import RunCommandBvt
# E0401: Unable to import 'lisa' (import-error)
from lisa import ( # pylint: disable=E0401
Logger,
Node,
TestCaseMetadata,
TestSuiteMetadata,
)
@TestSuiteMetadata(area="bvt", category="", description="Test suite for Agent BVTs")
class AgentBvt(AgentTestSuite):
"""
Test suite for Agent BVTs
"""
@TestCaseMetadata(description="", priority=0)
def main(self, node: Node, log: Logger) -> None:
self.execute(
node,
log,
[
ExtensionOperationsBvt, # Tests the basic operations (install, enable, update, uninstall) using CustomScript
RunCommandBvt,
VmAccessBvt
]
)

Просмотреть файл

@ -0,0 +1,4 @@
{
"name": "FailingTests",
"tests": ["fail_test.py", "error_test.py"]
}

Просмотреть файл

@ -0,0 +1,4 @@
{
"name": "PassingTest",
"tests": ["pass_test.py"]
}