Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
name = "ExtendedLocalCoverage"
uuid = "eb248270-a497-541c-8f75-6bb2aa2715dc"
version = "0.1.2"
authors = ["Alberto Mengali <a.mengali@gmail.com>"]
version = "0.1.1"

[deps]
CondaPkg = "992eb4ea-22a4-4c89-a5bb-47a3300528ab"
CoverageTools = "c36e975a-824b-4404-a568-ef97ca766997"
LocalCoverage = "5f6e1e16-694c-5876-87ef-16b5274f298e"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
Expand All @@ -17,6 +18,7 @@ CondaPkg = "0.2.24"
CoverageTools = "1.3.2"
LocalCoverage = "0.8.2"
Pkg = "1"
PrettyTables = "2, 3"
PythonCall = "0.9.23"
Revise = "3.7.1"
TOML = "1.0.3"
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
[![Lint workflow Status](https://github.com/disberd/ExtendedLocalCoverage.jl/actions/workflows/Lint.yml/badge.svg?branch=main)](https://github.com/disberd/ExtendedLocalCoverage.jl/actions/workflows/Lint.yml?query=branch%3Amain)
[![Docs workflow Status](https://github.com/disberd/ExtendedLocalCoverage.jl/actions/workflows/Docs.yml/badge.svg?branch=main)](https://github.com/disberd/ExtendedLocalCoverage.jl/actions/workflows/Docs.yml?query=branch%3Amain)
[![Coverage](https://codecov.io/gh/disberd/ExtendedLocalCoverage.jl/branch/main/graph/badge.svg)](https://codecov.io/gh/disberd/ExtendedLocalCoverage.jl)
[![DOI](https://zenodo.org/badge/DOI/FIXME)](https://doi.org/FIXME)
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md)
[![All Contributors](https://img.shields.io/github/all-contributors/disberd/ExtendedLocalCoverage.jl?labelColor=5e1ec7&color=c0ffee&style=flat-square)](#contributors)
[![BestieTemplate](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/JuliaBesties/BestieTemplate.jl/main/docs/src/assets/badge.json)](https://github.com/JuliaBesties/BestieTemplate.jl)
Expand All @@ -17,6 +16,9 @@ This package simply extends the functionality of [LocalCoverage.jl](https://gith
- Automatically create an xml cobertura coverage and an html report using `pycobertura`.
- The `pycobertura` library is automatically installed and used thanks to `CondaPkg.jl` and `PythonCall.jl`, not requiring the user to manually install python or `lcov` which is only available on non-windows systems.

This package was mainly created to provide easier access to code coverage within a private self-hosted gitlab instance, where codecov can not be used as is, but an HTML coverage report can be directly integrated within the gitlab web interface.

It is also convenient for getting an HTML coverage report locally without always relying on codecov from GH actions.

You can see an example of the generated HTML coverage report [here](https://disberd.github.io/ExtendedLocalCoverage.jl/coverage_example/), which was generated by calling `generate_package_coverage(; force_paths_relative = true)` on the [PlutoPlotly.jl](https://github.com/JuliaPluto/PlutoPlotly.jl) package.

Expand All @@ -35,7 +37,7 @@ Pkg.add(url="https://github.com/disberd/ExtendedLocalCoverage.jl")
For the basic usage which automatically extracts source files (including extensions) and generates the coverage report both in xml and html format, you can simply do the following (within the env of the package you are developing and making sure you have ExtendedLocalCoverage.jl in the `LOAD_PATH`):
```julia
using ExtendedLocalCoverage
generate_package_coverage()
cov_data = generate_package_coverage();
```

See the [developer documentation](https://disberd.github.io/ExtendedLocalCoverage.jl/dev) for more details.
Expand Down
5 changes: 4 additions & 1 deletion src/ExtendedLocalCoverage.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import Pkg

export generate_package_coverage, generate_html_report

# This is a temporary fix to fix PrettyTables issues until https://github.com/JuliaCI/LocalCoverage.jl/pull/68 is merged.
include("show_fix.jl")

function extract_package_info(pkg_dir)
project_toml = TOML.tryparsefile(joinpath(pkg_dir, "Project.toml"))
pkg_name = project_toml["name"]
Expand Down Expand Up @@ -105,7 +108,7 @@ function generate_package_coverage(pkg = nothing; use_existing_lcov = false, run
return true
end
LocalCoverage.generate_coverage(pkg; run_test, test_args, folder_list=[], file_list)
end
end |> WrappedPackageCoverage
if print_to_stdout
show(IOContext(stdout, :print_gaps => true), cov)
end
Expand Down
89 changes: 89 additions & 0 deletions src/show_fix.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
using LocalCoverage: PackageCoverage, format_line
using PrettyTables: PrettyTables, pretty_table

"""
WrappedPackageCoverage(summary::PackageCoverage)

Structure wrapping the `PackageCoverage` struct to add a custom `show` method for fixing PrettyTables issues until https://github.com/JuliaCI/LocalCoverage.jl/pull/68 is merged.
"""
struct WrappedPackageCoverage
summary::PackageCoverage
end

function Base.show(io::IO, wrapped::WrappedPackageCoverage)
(; summary) = wrapped
(; files, package_dir) = summary
row_data = map(format_line, files)
push!(row_data, format_line(summary))
row_coverage = map(x -> x.coverage_percentage, row_data)
rows = map(row_data) do row
(; name, total, hit, missed, coverage_percentage, gaps) = row
percentage = isnan(coverage_percentage) ? "-" : "$(round(Int, coverage_percentage))%"
(; name, total, hit, missed, percentage, gaps)
end
header = ["Filename", "Lines", "Hit", "Miss", "%"]
percentage_column = length(header)
alignment = [:l, :r, :r, :r, :r]
columns_width = fill(-1, 5) # We need strictly negative number to autosize in PrettyTables 3.0, but this also works in v2
if get(io, :print_gaps, false)
push!(header, "Gaps")
push!(alignment, :l)
display_cols = last(get(io, :displaysize, 100))
push!(columns_width, display_cols - 45)
else
rows = map(row -> Base.structdiff(row, NamedTuple{(:gaps,)}), rows)
end
# PrettyTables 3.0 changed Highlighter to TextHighlighter, which up to currently published version (v3.10) does not provide the kwargs constructor (despite having it documented). We create here a patch to handle both cases
Highlighter(f; kwargs...) = @static if pkgversion(PrettyTables) < v"3.0.0"
PrettyTables.Highlighter(f; kwargs...)
else
PrettyTables.TextHighlighter(f, PrettyTables.Crayon(;kwargs...))
end

highlighters = (
Highlighter(
(data, i, j) -> j == percentage_column && row_coverage[i] <= 50,
bold = true,
foreground = :red,
),
Highlighter((data, i, j) -> j == percentage_column && row_coverage[i] <= 70,
foreground = :yellow),
Highlighter((data, i, j) -> j == percentage_column && row_coverage[i] >= 90,
foreground = :green),
)

# Kwargs of `pretty_table` itself also changed in PrettyTables 3.0, so we have to branch here as well
@static if pkgversion(PrettyTables) < v"3.0.0"
pretty_table(
io,
rows;
title = "Coverage of $(package_dir)",
header,
alignment,
crop = :none,
linebreaks = true,
columns_width,
autowrap = true,
highlighters,
body_hlines = [length(rows) - 1],
)
else
pretty_table(
io,
rows;
title = "Coverage of $(package_dir)",
column_labels = [header],
alignment,
# The crop kwarg is not present anymore, split into the next two ones
fit_table_in_display_horizontally = false,
fit_table_in_display_vertically = false,
line_breaks = true,
fixed_data_column_widths = columns_width,
auto_wrap = true,
highlighters = collect(highlighters), # v3 expects a vector instead of a Tuple
table_format = PrettyTables.TextTableFormat(;
horizontal_lines_at_data_rows = [length(rows) - 1],
),
)
end
end