-
Notifications
You must be signed in to change notification settings - Fork 118
/
run_tests.py
executable file
·183 lines (153 loc) · 6.79 KB
/
run_tests.py
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#!/usr/bin/env python
"""
Based on template in rc/run_tests.binpy.py.in
"""
import os
import sqlite3
import sys
import re
def is_cibuildwheel():
"""Check if run with cibuildwheel."""
return 'CIBUILDWHEEL' in os.environ
# def temp_rename_kernprof(repo_dir):
# """
# Hacky workaround so kernprof.py doesn't get covered twice (installed and local).
# This needed to combine the .coverage files, since file paths need to be unique.
# """
# original_path = repo_dir + '/kernprof.py'
# tmp_path = original_path + '.tmp'
# if os.path.isfile(original_path):
# os.rename(original_path, tmp_path)
# elif os.path.isfile(tmp_path):
# os.rename(tmp_path, original_path)
def replace_docker_path(path, runner_project_dir):
"""Update path to a file installed in a temp venv to runner_project_dir."""
pattern = re.compile(r"\/tmp\/.+?\/site-packages")
return pattern.sub(runner_project_dir, path)
def update_coverage_file(coverage_path, runner_project_dir):
"""
Since the paths inside of docker vary from the runner paths,
the paths in the .coverage file need to be adjusted to combine them,
since 'coverage combine <folder>' checks if the file paths exist.
"""
try:
sqliteConnection = sqlite3.connect(coverage_path)
cursor = sqliteConnection.cursor()
print('Connected to Coverage SQLite')
read_file_query = 'SELECT id, path from file'
cursor.execute(read_file_query)
old_records = cursor.fetchall()
new_records = [(replace_docker_path(path, runner_project_dir), _id) for _id, path in old_records]
print('Updated coverage file paths:\n', new_records)
sql_update_query = 'Update file set path = ? where id = ?'
cursor.executemany(sql_update_query, new_records)
sqliteConnection.commit()
print('Coverage Updated successfully')
cursor.close()
except sqlite3.Error as error:
print('Failed to coverage: ', error)
finally:
if sqliteConnection:
sqliteConnection.close()
print('The sqlite connection is closed')
def copy_coverage_cibuildwheel_docker(runner_project_dir):
"""
When run with cibuildwheel under linux, the tests run in the folder /project
inside docker and the coverage files need to be copied to the output folder.
"""
coverage_path = '/project/tests/.coverage'
if os.path.isfile(coverage_path):
update_coverage_file(coverage_path, runner_project_dir)
env_hash = hash((sys.version, os.environ.get('AUDITWHEEL_PLAT', '')))
os.makedirs('/output', exist_ok=True)
os.rename(coverage_path, '/output/.coverage.{}'.format(env_hash))
def main():
import pathlib
orig_cwd = os.getcwd()
repo_dir = pathlib.Path(__file__).parent.absolute()
test_dir = repo_dir / 'tests'
print('[run_tests] cwd = {!r}'.format(orig_cwd))
print('[run_tests] Changing dirs to test_dir={!r}'.format(test_dir))
os.chdir(test_dir)
testdir_contents = list(pathlib.Path(test_dir).glob('*'))
pyproject_fpath = repo_dir / 'pyproject.toml'
print(f'[run_tests] repo_dir = {repo_dir}')
print(f'[run_tests] pyproject_fpath = {pyproject_fpath}')
print(f'[run_tests] test_dir={test_dir}')
# Prefer testing the installed version, but fallback to testing the
# development version.
try:
import ubelt as ub
except ImportError:
print('running this test script requires ubelt')
raise
print(f'[run_tests] testdir_contents = {ub.urepr(testdir_contents, nl=1)}')
print(f'[run_tests] sys.path = {ub.urepr(sys.path, nl=1)}')
package_name = 'line_profiler'
# Statically check if ``package_name`` is installed outside of the repo.
# To do this, we make a copy of PYTHONPATH, remove the repodir, and use
# ubelt to check to see if ``package_name`` can be resolved to a path.
temp_path = [pathlib.Path(p).resolve() for p in sys.path]
_resolved_repo_dir = repo_dir.resolve()
print(f'[run_tests] Searching for installed version of {package_name}.')
try:
_idx = temp_path.index(_resolved_repo_dir)
except IndexError:
print('[run_tests] Confirmed repo dir is not in sys.path')
else:
print(f'[run_tests] Removing _resolved_repo_dir={_resolved_repo_dir} from search path')
del temp_path[_idx]
if is_cibuildwheel():
# Remove from sys.path to prevent the import mechanism from testing
# the source repo rather than the installed wheel.
print(f'[run_tests] Removing _resolved_repo_dir={_resolved_repo_dir} from sys.path to ensure wheels are tested')
del sys.path[_idx]
print(f'[run_tests] sys.path = {ub.urepr(sys.path, nl=1)}')
_temp_path = [os.fspath(p) for p in temp_path]
print(f'[run_tests] Search Paths: {ub.urepr(_temp_path, nl=1)}')
modpath = ub.modname_to_modpath(package_name, sys_path=_temp_path)
if modpath is not None:
# If it does, then import it. This should cause the installed version
# to be used on further imports even if the repo_dir is in the path.
print(f'[run_tests] Found installed version of {package_name}')
print(f'[run_tests] modpath={modpath}')
modpath_contents = list(pathlib.Path(modpath).glob('*'))
print(f'[run_tests] modpath_contents = {ub.urepr(modpath_contents, nl=1)}')
# module = ub.import_module_from_path(modpath, index=0)
# print(f'[run_tests] Installed module = {module!r}')
else:
print(f'[run_tests] No installed version of {package_name} found')
# disable coverage in cibuildwheel for now
use_coverage = not is_cibuildwheel()
try:
import pytest
pytest_args = []
if use_coverage:
pytest_args += [
'--cov-config', os.fspath(pyproject_fpath),
'--cov-report', 'html',
'--cov-report', 'term',
'--cov-report', 'xml',
'--cov=' + package_name,
]
pytest_args += [
os.fspath(modpath), os.fspath(test_dir)
]
if is_cibuildwheel() and use_coverage:
pytest_args.append('--cov-append')
pytest_args = pytest_args + sys.argv[1:]
print(f'[run_tests] Exec pytest with args={pytest_args}')
retcode = pytest.main(pytest_args)
print(f'[run_tests] pytest returned ret={retcode}')
except Exception as ex:
print(f'[run_tests] pytest exception: {ex}')
retcode = 1
finally:
os.chdir(orig_cwd)
if is_cibuildwheel() and use_coverage:
# for CIBW under linux
copy_coverage_cibuildwheel_docker(f'/home/runner/work/{package_name}/{package_name}')
print('[run_tests] Restoring cwd = {!r}'.format(orig_cwd))
return retcode
if __name__ == '__main__':
sys.exit(main())