File: run.py

package info (click to toggle)
azure-cli 2.82.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,359,416 kB
  • sloc: python: 1,910,381; sh: 1,343; makefile: 406; cs: 145; javascript: 74; sql: 37; xml: 21
file content (143 lines) | stat: -rw-r--r-- 4,792 bytes parent folder | download | duplicates (2)
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import collections
import os
import os.path
import sys

import automation.tests.nose_helper as automation_tests
import automation.utilities.path as automation_path
from azure.cli.testsdk.vcr_test_base import COMMAND_COVERAGE_CONTROL_ENV


# pylint: disable=too-few-public-methods
class CommandCoverageContext:
    FILE_NAME = 'command_coverage.txt'

    def __init__(self, data_file_path):
        self._data_file_path = os.path.join(data_file_path, self.FILE_NAME)

    def __enter__(self):
        os.environ[COMMAND_COVERAGE_CONTROL_ENV] = self._data_file_path
        automation_path.make_dirs(os.path.dirname(self.coverage_file_path))
        with open(self.coverage_file_path, 'w') as f:
            f.write('')

        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        del os.environ[COMMAND_COVERAGE_CONTROL_ENV]

    @property
    def coverage_file_path(self):
        return self._data_file_path


def run_command_coverage(modules):
    test_result_dir = automation_path.get_test_results_dir(with_timestamp=True, prefix='cmdcov')
    data_file = os.path.join(test_result_dir, 'cmdcov.data')

    # run tests to generate executed command list
    run_nose = automation_tests.get_nose_runner(test_result_dir, parallel=False)

    with CommandCoverageContext(data_file) as context:
        for name, path in modules:
            run_nose(name, path)

        print('BEGIN: Full executed commands list')
        for line in open(context.coverage_file_path):
            sys.stdout.write(line)
        print('END: Full executed commands list')


# pylint: disable=too-few-public-methods
class CoverageContext:
    def __init__(self):
        from coverage import Coverage
        self._cov = Coverage(cover_pylib=False)
        self._cov.start()

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self._cov.stop()


def run_code_coverage(modules):
    # create test results folder
    test_results_folder = automation_path.get_test_results_dir(with_timestamp=True, prefix='cover')

    # get test runner
    run_nose = automation_tests.get_nose_runner(
        test_results_folder, code_coverage=True, parallel=False)

    # run code coverage on each project
    for name, _, test_path in modules:
        with CoverageContext():
            run_nose(name, test_path)

        import shutil
        shutil.move('.coverage', os.path.join(test_results_folder, '.coverage.{}'.format(name)))


def coverage_command_rundown(log_file_path):
    import azure.cli.core.application

    config = azure.cli.core.application.Configuration([])
    azure.cli.core.application.APPLICATION = azure.cli.core.application.Application(config)
    existing_commands = set(config.get_command_table().keys())

    command_counter = collections.defaultdict(lambda: 0)
    for line in open(log_file_path, 'r'):
        command = line.split(' -', 1)[0].strip()
        if command:
            command_counter[command] += 1

    print('COUNT\tCOMMAND')
    for c in sorted(command_counter.keys()):
        print('{}\t{}'.format(command_counter[c], c))

    print('\nUncovered commands:')
    for c in sorted(existing_commands - set(command_counter.keys())):
        print(c)


def main():
    import argparse
    parser = argparse.ArgumentParser('Code coverage tools')
    parser.add_argument('--command-coverage', action='store_true', help='Run command coverage')
    parser.add_argument('--code-coverage', action='store_true', help='Run code coverage')
    parser.add_argument('--module', action='append', dest='modules',
                        help='The modules to run coverage. Multiple modules can be fed.')
    parser.add_argument('--command-rundown', action='store',
                        help='Analyze a command coverage test result.')
    args = parser.parse_args()

    selected_modules = automation_path.filter_user_selected_modules(args.modules)
    if not selected_modules:
        parser.print_help()
        sys.exit(1)

    if not args.code_coverage and not args.command_coverage and not args.command_rundown:
        parser.print_help()
        sys.exit(1)

    if args.command_rundown:
        coverage_command_rundown(args.command_rundown)
        sys.exit(0)

    if args.code_coverage:
        run_code_coverage(selected_modules)

    if args.command_coverage:
        run_command_coverage(selected_modules)

    sys.exit(0)


if __name__ == '__main__':
    main()