[#270] Updates related to testing platform

Signed-off-by: a.berezin <a.berezin@yadro.com>
This commit is contained in:
Andrey Berezin 2024-07-26 16:34:47 +03:00
parent 166e44da9c
commit 7a500330de
8 changed files with 168 additions and 34 deletions

108
.devenv.hosting.yaml Normal file
View file

@ -0,0 +1,108 @@
hosts:
- address: localhost
attributes:
sudo_shell: false
plugin_name: docker
healthcheck_plugin_name: basic
attributes:
skip_readiness_check: True
force_transactions: True
services:
- name: frostfs-storage_01
attributes:
container_name: s01
config_path: /etc/frostfs/storage/config.yml
wallet_path: ../frostfs-dev-env/services/storage/wallet01.json
local_wallet_config_path: ./TemporaryDir/empty-password.yml
local_wallet_path: ../frostfs-dev-env/services/storage/wallet01.json
wallet_password: ""
volume_name: storage_storage_s01
endpoint_data0: s01.frostfs.devenv:8080
control_endpoint: s01.frostfs.devenv:8081
un_locode: "RU MOW"
- name: frostfs-storage_02
attributes:
container_name: s02
config_path: /etc/frostfs/storage/config.yml
wallet_path: ../frostfs-dev-env/services/storage/wallet02.json
local_wallet_config_path: ./TemporaryDir/empty-password.yml
local_wallet_path: ../frostfs-dev-env/services/storage/wallet02.json
wallet_password: ""
volume_name: storage_storage_s02
endpoint_data0: s02.frostfs.devenv:8080
control_endpoint: s02.frostfs.devenv:8081
un_locode: "RU LED"
- name: frostfs-storage_03
attributes:
container_name: s03
config_path: /etc/frostfs/storage/config.yml
wallet_path: ../frostfs-dev-env/services/storage/wallet03.json
local_wallet_config_path: ./TemporaryDir/empty-password.yml
local_wallet_path: ../frostfs-dev-env/services/storage/wallet03.json
wallet_password: ""
volume_name: storage_storage_s03
endpoint_data0: s03.frostfs.devenv:8080
control_endpoint: s03.frostfs.devenv:8081
un_locode: "SE STO"
- name: frostfs-storage_04
attributes:
container_name: s04
config_path: /etc/frostfs/storage/config.yml
wallet_path: ../frostfs-dev-env/services/storage/wallet04.json
local_wallet_config_path: ./TemporaryDir/empty-password.yml
local_wallet_path: ../frostfs-dev-env/services/storage/wallet04.json
wallet_password: ""
volume_name: storage_storage_s04
endpoint_data0: s04.frostfs.devenv:8080
control_endpoint: s04.frostfs.devenv:8081
un_locode: "FI HEL"
- name: frostfs-s3_01
attributes:
container_name: s3_gate
config_path: ../frostfs-dev-env/services/s3_gate/.s3.env
wallet_path: ../frostfs-dev-env/services/s3_gate/wallet.json
local_wallet_config_path: ./TemporaryDir/password-s3.yml
local_wallet_path: ../frostfs-dev-env/services/s3_gate/wallet.json
wallet_password: "s3"
endpoint_data0: https://s3.frostfs.devenv:8080
- name: frostfs-http_01
attributes:
container_name: http_gate
config_path: ../frostfs-dev-env/services/http_gate/.http.env
wallet_path: ../frostfs-dev-env/services/http_gate/wallet.json
local_wallet_config_path: ./TemporaryDir/password-other.yml
local_wallet_path: ../frostfs-dev-env/services/http_gate/wallet.json
wallet_password: "one"
endpoint_data0: http://http.frostfs.devenv
- name: frostfs-ir_01
attributes:
container_name: ir01
config_path: ../frostfs-dev-env/services/ir/.ir.env
wallet_path: ../frostfs-dev-env/services/ir/az.json
local_wallet_config_path: ./TemporaryDir/password-other.yml
local_wallet_path: ../frostfs-dev-env/services/ir/az.json
wallet_password: "one"
- name: neo-go_01
attributes:
container_name: morph_chain
config_path: ../frostfs-dev-env/services/morph_chain/protocol.privnet.yml
wallet_path: ../frostfs-dev-env/services/morph_chain/node-wallet.json
local_wallet_config_path: ./TemporaryDir/password-other.yml
local_wallet_path: ../frostfs-dev-env/services/morph_chain/node-wallet.json
wallet_password: "one"
endpoint_internal0: http://morph-chain.frostfs.devenv:30333
- name: main-chain_01
attributes:
container_name: main_chain
config_path: ../frostfs-dev-env/services/chain/protocol.privnet.yml
wallet_path: ../frostfs-dev-env/services/chain/node-wallet.json
local_wallet_config_path: ./TemporaryDir/password-other.yml
local_wallet_path: ../frostfs-dev-env/services/chain/node-wallet.json
wallet_password: "one"
endpoint_internal0: http://main-chain.frostfs.devenv:30333
- name: coredns_01
attributes:
container_name: coredns
clis:
- name: frostfs-cli
exec_path: frostfs-cli

View file

@ -89,4 +89,7 @@ push = false
filterwarnings = [ filterwarnings = [
"ignore:Blowfish has been deprecated:cryptography.utils.CryptographyDeprecationWarning", "ignore:Blowfish has been deprecated:cryptography.utils.CryptographyDeprecationWarning",
] ]
testpaths = ["tests"] testpaths = ["tests"]
[project.entry-points.pytest11]
testlib = "frostfs_testlib"

View file

@ -1 +1,3 @@
__version__ = "2.0.1" __version__ = "2.0.1"
from .fixtures import configure_testlib, hosting

View file

@ -1,5 +1,5 @@
from frostfs_testlib.analytics import test_case from frostfs_testlib.analytics import test_case
from frostfs_testlib.analytics.test_case import TestCasePriority from frostfs_testlib.analytics.test_case import TestCasePriority
from frostfs_testlib.analytics.test_collector import TestCase, TestCaseCollector from frostfs_testlib.analytics.test_collector import TestCase, TestCaseCollector
from frostfs_testlib.analytics.test_exporter import TestExporter from frostfs_testlib.analytics.test_exporter import TСExporter
from frostfs_testlib.analytics.testrail_exporter import TestrailExporter from frostfs_testlib.analytics.testrail_exporter import TestrailExporter

View file

@ -3,7 +3,8 @@ from abc import ABC, abstractmethod
from frostfs_testlib.analytics.test_collector import TestCase from frostfs_testlib.analytics.test_collector import TestCase
class TestExporter(ABC): # TODO: REMOVE ME
class TСExporter(ABC):
test_cases_cache = [] test_cases_cache = []
test_suites_cache = [] test_suites_cache = []
@ -46,9 +47,7 @@ class TestExporter(ABC):
""" """
@abstractmethod @abstractmethod
def update_test_case( def update_test_case(self, test_case: TestCase, test_case_in_tms, test_suite, test_suite_section) -> None:
self, test_case: TestCase, test_case_in_tms, test_suite, test_suite_section
) -> None:
""" """
Update test case in TMS Update test case in TMS
""" """
@ -60,9 +59,7 @@ class TestExporter(ABC):
for test_case in test_cases: for test_case in test_cases:
test_suite = self.get_or_create_test_suite(test_case.suite_name) test_suite = self.get_or_create_test_suite(test_case.suite_name)
test_section = self.get_or_create_suite_section( test_section = self.get_or_create_suite_section(test_suite, test_case.suite_section_name)
test_suite, test_case.suite_section_name
)
test_case_in_tms = self.search_test_case_id(test_case.id) test_case_in_tms = self.search_test_case_id(test_case.id)
steps = [{"content": value, "expected": " "} for key, value in test_case.steps.items()] steps = [{"content": value, "expected": " "} for key, value in test_case.steps.items()]

View file

@ -1,10 +1,10 @@
from testrail_api import TestRailAPI from testrail_api import TestRailAPI
from frostfs_testlib.analytics.test_collector import TestCase from frostfs_testlib.analytics.test_collector import TestCase
from frostfs_testlib.analytics.test_exporter import TestExporter from frostfs_testlib.analytics.test_exporter import TСExporter
class TestrailExporter(TestExporter): class TestrailExporter(TСExporter):
def __init__( def __init__(
self, self,
tr_url: str, tr_url: str,
@ -62,19 +62,13 @@ class TestrailExporter(TestExporter):
It's help do not call TMS each time then we search test case It's help do not call TMS each time then we search test case
""" """
for test_suite in self.test_suites_cache: for test_suite in self.test_suites_cache:
self.test_cases_cache.extend( self.test_cases_cache.extend(self.api.cases.get_cases(self.tr_project_id, suite_id=test_suite["id"]))
self.api.cases.get_cases(self.tr_project_id, suite_id=test_suite["id"])
)
def search_test_case_id(self, test_case_id: str) -> object: def search_test_case_id(self, test_case_id: str) -> object:
""" """
Find test cases in TestRail (cache) by ID Find test cases in TestRail (cache) by ID
""" """
test_cases = [ test_cases = [test_case for test_case in self.test_cases_cache if test_case["custom_autotest_name"] == test_case_id]
test_case
for test_case in self.test_cases_cache
if test_case["custom_autotest_name"] == test_case_id
]
if len(test_cases) > 1: if len(test_cases) > 1:
raise RuntimeError(f"Too many results found in test rail for id {test_case_id}") raise RuntimeError(f"Too many results found in test rail for id {test_case_id}")
@ -87,9 +81,7 @@ class TestrailExporter(TestExporter):
""" """
Get suite name with exact name from Testrail or create if not exist Get suite name with exact name from Testrail or create if not exist
""" """
test_rail_suites = [ test_rail_suites = [suite for suite in self.test_suites_cache if suite["name"] == test_suite_name]
suite for suite in self.test_suites_cache if suite["name"] == test_suite_name
]
if not test_rail_suites: if not test_rail_suites:
test_rail_suite = self.api.suites.add_suite( test_rail_suite = self.api.suites.add_suite(
@ -102,17 +94,13 @@ class TestrailExporter(TestExporter):
elif len(test_rail_suites) == 1: elif len(test_rail_suites) == 1:
return test_rail_suites.pop() return test_rail_suites.pop()
else: else:
raise RuntimeError( raise RuntimeError(f"Too many results found in test rail for suite name {test_suite_name}")
f"Too many results found in test rail for suite name {test_suite_name}"
)
def get_or_create_suite_section(self, test_rail_suite, section_name) -> object: def get_or_create_suite_section(self, test_rail_suite, section_name) -> object:
""" """
Get suite section with exact name from Testrail or create new one if not exist Get suite section with exact name from Testrail or create new one if not exist
""" """
test_rail_sections = [ test_rail_sections = [section for section in test_rail_suite["sections"] if section["name"] == section_name]
section for section in test_rail_suite["sections"] if section["name"] == section_name
]
if not test_rail_sections: if not test_rail_sections:
test_rail_section = self.api.sections.add_section( test_rail_section = self.api.sections.add_section(
@ -128,9 +116,7 @@ class TestrailExporter(TestExporter):
elif len(test_rail_sections) == 1: elif len(test_rail_sections) == 1:
return test_rail_sections.pop() return test_rail_sections.pop()
else: else:
raise RuntimeError( raise RuntimeError(f"Too many results found in test rail for section name {section_name}")
f"Too many results found in test rail for section name {section_name}"
)
def prepare_request_body(self, test_case: TestCase, test_suite, test_suite_section) -> dict: def prepare_request_body(self, test_case: TestCase, test_suite, test_suite_section) -> dict:
""" """
@ -164,9 +150,7 @@ class TestrailExporter(TestExporter):
self.api.cases.add_case(**request_body) self.api.cases.add_case(**request_body)
def update_test_case( def update_test_case(self, test_case: TestCase, test_case_in_tms, test_suite, test_suite_section) -> None:
self, test_case: TestCase, test_case_in_tms, test_suite, test_suite_section
) -> None:
""" """
Update test case in Testrail Update test case in Testrail
""" """

View file

@ -0,0 +1,35 @@
import logging
import os
from importlib.metadata import entry_points
import pytest
import yaml
from frostfs_testlib import reporter
from frostfs_testlib.hosting.hosting import Hosting
from frostfs_testlib.resources.common import HOSTING_CONFIG_FILE
from frostfs_testlib.storage import get_service_registry
@pytest.fixture(scope="session")
def configure_testlib():
reporter.get_reporter().register_handler(reporter.AllureHandler())
reporter.get_reporter().register_handler(reporter.StepsLogger())
logging.getLogger("paramiko").setLevel(logging.INFO)
# Register Services for cluster
registry = get_service_registry()
services = entry_points(group="frostfs.testlib.services")
for svc in services:
registry.register_service(svc.name, svc.load())
@pytest.fixture(scope="session")
def hosting(configure_testlib) -> Hosting:
with open(HOSTING_CONFIG_FILE, "r") as file:
hosting_config = yaml.full_load(file)
hosting_instance = Hosting()
hosting_instance.configure(hosting_config)
return hosting_instance

View file

@ -46,3 +46,8 @@ with open(DEFAULT_WALLET_CONFIG, "w") as file:
MAX_REQUEST_ATTEMPTS = 5 MAX_REQUEST_ATTEMPTS = 5
RETRY_MODE = "standard" RETRY_MODE = "standard"
CREDENTIALS_CREATE_TIMEOUT = "1m" CREDENTIALS_CREATE_TIMEOUT = "1m"
HOSTING_CONFIG_FILE = os.getenv(
"HOSTING_CONFIG_FILE", os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..", ".devenv.hosting.yaml"))
)