()
| 163 | |
| 164 | |
| 165 | def main() -> None: |
| 166 | parser = argparse.ArgumentParser( |
| 167 | prog="ci-coverage-pr-report", |
| 168 | formatter_class=argparse.RawDescriptionHelpFormatter, |
| 169 | description=""" |
| 170 | ci-coverage-pr-report creates a code coverage report for CI.""", |
| 171 | ) |
| 172 | |
| 173 | parser.add_argument("--unittests", type=str, help="unit test lcov file") |
| 174 | parser.add_argument("tests", nargs="+", help="all other lcov files from test runs") |
| 175 | args = parser.parse_args() |
| 176 | |
| 177 | result = subprocess.run(["git", "diff"], check=True, capture_output=True) |
| 178 | output = result.stdout.decode("utf-8").strip() |
| 179 | assert not output, f"Has to run on clean git state: \n{output}" |
| 180 | |
| 181 | test_cases = [] |
| 182 | |
| 183 | coverage: Coverage = {} |
| 184 | for file, line in buildkite.find_modified_lines(): |
| 185 | if not ignore_file_in_coverage_report(file): |
| 186 | coverage.setdefault(file, OrderedDict())[line] = None |
| 187 | |
| 188 | for lcov_file in args.tests: |
| 189 | mark_covered_lines(lcov_file, coverage) |
| 190 | if args.unittests: |
| 191 | if os.path.isfile(args.unittests): |
| 192 | mark_covered_lines(args.unittests, coverage, unittests=True) |
| 193 | else: |
| 194 | test_case = junit_xml.TestCase("Unit Tests", "Code Coverage") |
| 195 | test_case.add_error_info(message="No coverage for unit tests available") |
| 196 | test_cases.append(test_case) |
| 197 | |
| 198 | unit_test_only_report = get_report( |
| 199 | coverage, |
| 200 | lambda lines, i, line: bool( |
| 201 | (lines.get(i + 1) or 0) >= 0 or IGNORE_SRC_LINE_RE.search(line) |
| 202 | ), |
| 203 | ) |
| 204 | # If a line has "None" marker, then it can't be covered, print it out. |
| 205 | # If a line has positive or negative coverage then it is |
| 206 | # covered in normal tests or unit tests, print it out. |
| 207 | # All remaining lines can be covered, but are not covered. |
| 208 | uncovered_report = get_report( |
| 209 | coverage, |
| 210 | lambda lines, i, line: bool( |
| 211 | lines.get(i + 1) is None |
| 212 | or (lines.get(i + 1) or 0) != 0 |
| 213 | or IGNORE_SRC_LINE_RE.search(line) |
| 214 | ), |
| 215 | ) |
| 216 | |
| 217 | test_case = junit_xml.TestCase("Uncovered Lines in PR", "Code Coverage") |
| 218 | if len(uncovered_report): |
| 219 | print("Uncovered Lines in PR") |
| 220 | # Buildkite interprets the +++ and --- chars at the start of line, put |
| 221 | # in a zero-width space as a workaround. |
| 222 | ZWSP = "\u200b" |
no test coverage detected