.\" -*- mode: troff; coding: utf-8 -*- .\" Automatically generated by Pod::Man v6.0.2 (Pod::Simple 3.45) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. .ie n \{\ . ds C` "" . ds C' "" 'br\} .el\{\ . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Required to disable full justification in groff 1.23.0. .if n .ds AD l .\" ======================================================================== .\" .IX Title "Devel::Cover::Collection 3" .TH Devel::Cover::Collection 3 2026-03-09 "perl v5.42.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH NAME Devel::Cover::Collection \- Code coverage for a collection of modules .SH VERSION .IX Header "VERSION" version 1.52 .SH SYNOPSIS .IX Header "SYNOPSIS" .Vb 1 \& use Devel::Cover::Collection; \& \& my $collection = Devel::Cover::Collection\->new( \& results_dir => "/path/to/results", \& bin_dir => "/path/to/bin", \& workers => 4, \& verbose => 1, \& ); \& \& # Add modules to process \& $collection\->add_modules("Some::Module", "Another::Module"); \& \& # Or load from a file \& $collection\->set_module_file("/path/to/modules.txt"); \& $collection\->process_module_file; \& \& # Run coverage collection \& $collection\->cover_modules; \& \& # Generate HTML reports \& $collection\->generate_html; .Ve .SH DESCRIPTION .IX Header "DESCRIPTION" Devel::Cover::Collection provides infrastructure for running code coverage analysis across a collection of CPAN modules. It is primarily used by the CPANCover service () to generate coverage reports for CPAN distributions. .PP The module supports: .IP \(bu 4 Parallel processing of multiple modules .IP \(bu 4 Docker\-based isolation for coverage runs .IP \(bu 4 HTML and JSON report generation .IP \(bu 4 Tracking of covered and failed modules .IP \(bu 4 Compression of old coverage results .PP This module requires Perl 5.42.0 or later and uses the builtin \f(CW\*(C`class\*(C'\fR feature. .SH CONSTRUCTOR .IX Header "CONSTRUCTOR" .SS new .IX Subsection "new" .Vb 1 \& my $collection = Devel::Cover::Collection\->new(%options); .Ve .PP Creates a new Collection object. All options are optional and have sensible defaults. .SH ATTRIBUTES .IX Header "ATTRIBUTES" .SS "Read\-Only Attributes" .IX Subsection "Read-Only Attributes" These attributes can only be set via the constructor. .PP \fIbin_dir\fR .IX Subsection "bin_dir" .PP Directory containing the \f(CW\*(C`cover\*(C'\fR binary. Used when running coverage commands. .PP \fIcpancover_dir\fR .IX Subsection "cpancover_dir" .PP Directory for CPANCover\-specific files and configuration. .PP \fIcpan_dir\fR .IX Subsection "cpan_dir" .PP An arrayref of CPAN directories to search for build directories. Defaults to \&\f(CW\*(C`~/.cpan\*(C'\fR and \f(CW\*(C`~/.local/share/.cpan\*(C'\fR if they exist. .PP \fIresults_dir\fR .IX Subsection "results_dir" .PP Directory where coverage results are stored. Required for most operations. .PP \fIdryrun\fR .IX Subsection "dryrun" .PP Boolean. If true, commands are printed but not executed. Default: 0. .PP \fIenv\fR .IX Subsection "env" .PP Environment identifier (e.g., \*(Aqprod\*(Aq, \*(Aqdev\*(Aq). Default: \*(Aqprod\*(Aq. .PP \fIforce\fR .IX Subsection "force" .PP Boolean. If true, re\-run coverage even for already\-covered modules. Default: 0. .PP \fIoutput_file\fR .IX Subsection "output_file" .PP Filename for the main output file. Default: \*(Aqindex.html\*(Aq. .PP \fIreport\fR .IX Subsection "report" .PP Report format to generate. Default: \*(Aqhtml_basic\*(Aq. .PP \fItimeout\fR .IX Subsection "timeout" .PP Timeout in seconds for coverage runs. Default: 1800 (30 minutes). .PP \fIverbose\fR .IX Subsection "verbose" .PP Boolean. If true, print additional progress information. Default: 0. .PP \fIworkers\fR .IX Subsection "workers" .PP Number of parallel workers for coverage runs. Default: 0 (no parallelism). .PP \fIdocker\fR .IX Subsection "docker" .PP Docker command to use. Default: \*(Aqdocker\*(Aq. .PP \fIlocal\fR .IX Subsection "local" .PP Boolean. If true, run in local mode without Docker. Default: 0. .SS "Read\-Write\-Private Attributes" .IX Subsection "Read-Write-Private Attributes" These attributes have public readers but private setters. Use the provided methods to modify them. .PP \fIbuild_dirs\fR .IX Subsection "build_dirs" .PP Arrayref of build directories to process. Modify via \f(CW\*(C`add_build_dirs\*(C'\fR. .PP \fImodules\fR .IX Subsection "modules" .PP Arrayref of module names to process. Modify via \f(CW\*(C`add_modules\*(C'\fR or \&\f(CW\*(C`set_modules\*(C'\fR. .PP \fImodule_file\fR .IX Subsection "module_file" .PP Path to a file containing module names (one per line). Set via \&\f(CW\*(C`set_module_file\*(C'\fR. .SS "Read\-Write Attributes" .IX Subsection "Read-Write Attributes" These attributes can be read and written directly. .PP \fIdir\fR .IX Subsection "dir" .PP .Vb 2 \& $collection\->dir("/path/to/dir"); \& my $dir = $collection\->dir; .Ve .PP Working directory for the current operation. .PP \fIfile\fR .IX Subsection "file" .PP .Vb 2 \& $collection\->file("/path/to/file"); \& my $file = $collection\->file; .Ve .PP Current file being processed. .SH METHODS .IX Header "METHODS" .SS "Module Management" .IX Subsection "Module Management" \fIadd_modules\fR .IX Subsection "add_modules" .PP .Vb 1 \& $collection\->add_modules(@module_names); .Ve .PP Appends modules to the list of modules to process. .PP \fIset_modules\fR .IX Subsection "set_modules" .PP .Vb 1 \& $collection\->set_modules(@module_names); .Ve .PP Replaces the entire module list with the given modules. .PP \fIset_module_file\fR .IX Subsection "set_module_file" .PP .Vb 1 \& $collection\->set_module_file("/path/to/modules.txt"); .Ve .PP Sets the path to a file containing module names. .PP \fIprocess_module_file\fR .IX Subsection "process_module_file" .PP .Vb 1 \& $collection\->process_module_file; .Ve .PP Reads module names from the file specified by \f(CW\*(C`module_file\*(C'\fR and adds them to the modules list. Blank lines and lines starting with \f(CW\*(C`#\*(C'\fR are ignored. .SS "Build Operations" .IX Subsection "Build Operations" \fIbuild_modules\fR .IX Subsection "build_modules" .PP .Vb 1 \& $collection\->build_modules; .Ve .PP Builds all modules in the modules list using \f(CW\*(C`cpan \-Ti\*(C'\fR. If \f(CW\*(C`force\*(C'\fR is true, uses the \f(CW\*(C`\-f\*(C'\fR flag. .PP \fIadd_build_dirs\fR .IX Subsection "add_build_dirs" .PP .Vb 1 \& $collection\->add_build_dirs; .Ve .PP Scans the CPAN directories for build directories and adds them to \&\f(CW\*(C`build_dirs\*(C'\fR. .PP \fIlocal_build\fR .IX Subsection "local_build" .PP .Vb 1 \& $collection\->local_build; .Ve .PP Orchestrates a complete local build workflow: processes the module file, builds modules, adds build directories, and runs coverage on all. .SS "Coverage Operations" .IX Subsection "Coverage Operations" \fIrun\fR .IX Subsection "run" .PP .Vb 1 \& $collection\->run($build_dir); .Ve .PP Runs coverage analysis on a single build directory. Creates coverage reports in the results directory. .PP \fIrun_all\fR .IX Subsection "run_all" .PP .Vb 1 \& $collection\->run_all; .Ve .PP Runs coverage analysis on all directories in \f(CW\*(C`build_dirs\*(C'\fR, using parallel workers if configured. .PP \fIcover_modules\fR .IX Subsection "cover_modules" .PP .Vb 1 \& $collection\->cover_modules; .Ve .PP Covers all modules using Docker containers. Processes the module file, then runs coverage for each module in parallel. .SS "Report Generation" .IX Subsection "Report Generation" \fIgenerate_html\fR .IX Subsection "generate_html" .PP .Vb 1 \& $collection\->generate_html; .Ve .PP Generates HTML coverage reports for all modules in the results directory. Creates an index page, per\-module pages, and an about page. .PP \fIcoverage_class\fR .IX Subsection "coverage_class" .PP .Vb 1 \& my $css_class = $collection\->coverage_class($percentage); .Ve .PP Converts a coverage percentage to a CSS class name for HTML reports: .PP .Vb 5 \& n/a \-> "na" \& < 75 \-> "c0" \& < 90 \-> "c1" \& < 100 \-> "c2" \& 100 \-> "c3" .Ve .PP \fIwrite_summary\fR .IX Subsection "write_summary" .PP .Vb 1 \& $collection\->write_summary($vars); .Ve .PP Writes the HTML summary pages using Template Toolkit. Called by \&\f(CW\*(C`generate_html\*(C'\fR. .PP \fIwrite_json\fR .IX Subsection "write_json" .PP .Vb 1 \& $collection\->write_json($vars); .Ve .PP Writes a JSON file (\f(CW\*(C`cpancover.json\*(C'\fR) containing coverage data for all modules. .SS "Status Tracking" .IX Subsection "Status Tracking" \fIis_covered\fR .IX Subsection "is_covered" .PP .Vb 1 \& if ($collection\->is_covered($module_dir)) { ... } .Ve .PP Returns true if coverage results exist for the given module directory. .PP \fIis_failed\fR .IX Subsection "is_failed" .PP .Vb 1 \& if ($collection\->is_failed($module_dir)) { ... } .Ve .PP Returns true if the module has been marked as failed. .PP \fIset_covered\fR .IX Subsection "set_covered" .PP .Vb 1 \& $collection\->set_covered($module_dir); .Ve .PP Marks a module as successfully covered (removes any failure marker). .PP \fIset_failed\fR .IX Subsection "set_failed" .PP .Vb 1 \& $collection\->set_failed($module_dir); .Ve .PP Marks a module as failed by creating a timestamp file in the failed directory. .SS "Path Methods" .IX Subsection "Path Methods" \fImade_res_dir\fR .IX Subsection "made_res_dir" .PP .Vb 2 \& my ($path, $output) = $collection\->made_res_dir; \& my ($path, $output) = $collection\->made_res_dir($subdir); .Ve .PP Creates and returns the results directory path. If \f(CW$subdir\fR is provided, creates that subdirectory within the results directory. .PP \fIcovered_dir\fR .IX Subsection "covered_dir" .PP .Vb 1 \& my $path = $collection\->covered_dir($module_dir); .Ve .PP Returns the path where coverage results for a module are stored. .PP \fIfailed_dir\fR .IX Subsection "failed_dir" .PP .Vb 1 \& my $path = $collection\->failed_dir; .Ve .PP Returns the path to the directory containing failure markers. .PP \fIfailed_file\fR .IX Subsection "failed_file" .PP .Vb 1 \& my $path = $collection\->failed_file($module_dir); .Ve .PP Returns the path to the failure marker file for a module. .PP \fIdc_file\fR .IX Subsection "dc_file" .PP .Vb 1 \& my $path = $collection\->dc_file; .Ve .PP Returns the path to the \f(CW\*(C`dc\*(C'\fR utility script. .SS Maintenance .IX Subsection "Maintenance" \fIcompress_old_versions\fR .IX Subsection "compress_old_versions" .PP .Vb 1 \& $collection\->compress_old_versions($num_versions_to_keep); .Ve .PP Compresses old coverage results, keeping only the specified number of most recent versions for each module. .PP \fIget_latest\fR .IX Subsection "get_latest" .PP .Vb 1 \& $collection\->get_latest; .Ve .PP Fetches and prints the latest CPAN release information using CPAN::Releases::Latest. .SS "System Commands" .IX Subsection "System Commands" \fIsys\fR .IX Subsection "sys" .PP .Vb 1 \& my $output = $collection\->sys(@command); .Ve .PP Runs a system command, displaying the first portion of output immediately and buffering the rest. Returns the output on success, empty string on failure. .PP \fIbsys\fR .IX Subsection "bsys" .PP .Vb 1 \& my $output = $collection\->bsys(@command); .Ve .PP Like \f(CW\*(C`sys\*(C'\fR, but buffers all output (no immediate display). .PP \fIfsys\fR .IX Subsection "fsys" .PP .Vb 1 \& my $output = $collection\->fsys(@command); .Ve .PP Like \f(CW\*(C`sys\*(C'\fR, but dies on failure. .PP \fIfbsys\fR .IX Subsection "fbsys" .PP .Vb 1 \& my $output = $collection\->fbsys(@command); .Ve .PP Like \f(CW\*(C`bsys\*(C'\fR, but dies on failure. .SH "EMBEDDED CLASSES" .IX Header "EMBEDDED CLASSES" .SS Devel::Cover::Collection::Template::Provider .IX Subsection "Devel::Cover::Collection::Template::Provider" A subclass of Template::Provider that provides built\-in templates for HTML report generation. The following templates are available: .IP \(bu 4 colours \- CSS colour definitions .IP \(bu 4 html \- Base HTML wrapper .IP \(bu 4 summary \- Main index page .IP \(bu 4 about \- About page .IP \(bu 4 module_by_start \- Module listing by first letter .SH DEPENDENCIES .IX Header "DEPENDENCIES" .IP \(bu 4 Perl 5.42.0 or later (for builtin \f(CW\*(C`class\*(C'\fR feature) .IP \(bu 4 Devel::Cover::DB .IP \(bu 4 JSON::MaybeXS .IP \(bu 4 Parallel::Iterator .IP \(bu 4 Template .IP \(bu 4 Time::HiRes .SH "SEE ALSO" .IX Header "SEE ALSO" Devel::Cover, .SH AUTHOR .IX Header "AUTHOR" Paul Johnson .SH LICENCE .IX Header "LICENCE" Copyright 2014\-2026, Paul Johnson (paul@pjcj.net) .PP This software is free. It is licensed under the same terms as Perl itself. .PP The latest version of this software should be available on CPAN and from my homepage: .