aboutsummaryrefslogtreecommitdiffstats
path: root/library/python/pytest/plugins/fixtures.py
blob: 8035a2bb20f4f378545501af77557bc6ecfb7fad (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import os
import pytest
import six 


MAX_ALLOWED_LINKS_COUNT = 10


@pytest.fixture
def metrics(request):

    class Metrics(object):
        @classmethod
        def set(cls, name, value):
            assert len(name) <= 128, "Length of the metric name must less than 128"
            assert type(value) in [int, float], "Metric value must be of type int or float"
            test_name = request.node.nodeid
            if test_name not in request.config.test_metrics:
                request.config.test_metrics[test_name] = {}
            request.config.test_metrics[test_name][name] = value

        @classmethod
        def set_benchmark(cls, benchmark_values):
            # report of google has key 'benchmarks' which is a list of benchmark results 
            # yandex benchmark has key 'benchmark', which is a list of benchmark results 
            # use this to differentiate which kind of result it is 
            if 'benchmarks' in benchmark_values: 
                cls.set_gbenchmark(benchmark_values) 
            else: 
                cls.set_ybenchmark(benchmark_values) 
 
        @classmethod 
        def set_ybenchmark(cls, benchmark_values): 
            for benchmark in benchmark_values["benchmark"]:
                name = benchmark["name"]
                for key, value in six.iteritems(benchmark):
                    if key != "name":
                        cls.set("{}_{}".format(name, key), value)

        @classmethod 
        def set_gbenchmark(cls, benchmark_values): 
            time_unit_multipliers = {"ns": 1, "us": 1000, "ms": 1000000} 
            time_keys = {"real_time", "cpu_time"} 
            ignore_keys = {"name", "run_name", "time_unit", "run_type", "repetition_index"} 
            for benchmark in benchmark_values["benchmarks"]: 
                name = benchmark["name"].replace('/', '_')  # ci does not work properly with '/' in metric name 
                time_unit_mult = time_unit_multipliers[benchmark.get("time_unit", "ns")] 
                for k, v in six.iteritems(benchmark): 
                    if k in time_keys: 
                        cls.set("{}_{}".format(name, k), v * time_unit_mult) 
                    elif k not in ignore_keys and isinstance(v, (float, int)): 
                        cls.set("{}_{}".format(name, k), v) 
    return Metrics


@pytest.fixture
def links(request):

    class Links(object):
        @classmethod
        def set(cls, name, path):

            if len(request.config.test_logs[request.node.nodeid]) >= MAX_ALLOWED_LINKS_COUNT:
                raise Exception("Cannot add more than {} links to test".format(MAX_ALLOWED_LINKS_COUNT))

            reserved_names = ["log", "logsdir", "stdout", "stderr"]
            if name in reserved_names:
                raise Exception("Attachment name should not belong to the reserved list: {}".format(", ".join(reserved_names)))
            output_dir = request.config.ya.output_dir

            if not os.path.exists(path):
                raise Exception("Path to be attached does not exist: {}".format(path))

            if os.path.isabs(path) and ".." in os.path.relpath(path, output_dir):
                raise Exception("Test attachment must be inside yatest.common.output_path()")

            request.config.test_logs[request.node.nodeid][name] = path

        @classmethod
        def get(cls, name):
            if name not in request.config.test_logs[request.node.nodeid]:
                raise KeyError("Attachment with name '{}' does not exist".format(name))
            return request.config.test_logs[request.node.nodeid][name]

    return Links