genbadge¶
Generate badges for tools that do not provide one.
genbadge
provides a set of commandline utilities to generate badges for tools that do not provide one. It currently can create:
tests
badges such as frompytest
or otherjunit.xml
-generating framework,coverage
badges such as from pythoncoverage
or othercoverage.xml
-generating framework,flake8
badges such as fromflake8 --statistics
.
Badges are either generated using the shields.io HTTP REST API, or with an equivalent local SVG template included in genbadge
.
Installing¶
Full¶
In order for all commandline features to work, you should install genbadge
with the extra dependencies:
> pip install genbadge[all]
This is equivalent to pip install genbadge[tests,coverage,flake8]
. Alternatively you can install dependencies for only a subset of commands for example pip install genbadge[tests,flake8]
.
Minimal¶
genbadge
core only requires click
(the CLI framework), pillow
(for SVG file templating) and requests
(to call the shields.io API). You can install it using
> pip install genbadge
This will only allow you to use the low-level API.
Usage¶
Once installed, genbadge
is available as a commandline utility. You can get some help with:
> genbadge
Usage: genbadge [OPTIONS] COMMAND [ARGS]...
Commandline utility to generate badges. To get help on each command use:
genbadge <cmd> --help
Options:
--help Show this message and exit.
Commands:
coverage Generate a badge for the coverage results (e.g. from a
coverage.xml).
flake8 Generate a badge for the flake8 results (e.g. from a flake8stats.txt
file).
tests Generate a badge for the test results (e.g. from a junit.xml).
1. Tests badge¶
Prerequisite: a test report¶
a. pytest
¶
If you use pytest
, you can use some options to generate test reports:
-
with
--junitxml=path/to/junit.xml
a junit-format report is generated. This is the file that we'll need to generate the badge. -
with
--html=path/to/report.html
a detailed HTML report is generated. This is not required to generate the badge, but you might wish to use it so that users navigate to it when they will click on your badge.
Security concerns
Test reports might contain secrets (keys, env variables, OS user names containing employee numbers, etc.), so always review them carefully before publishing them !
Let's run this in your project:
> pytest --junitxml=reports/junit/junit.xml --html=reports/junit/report.html
You can check that the two files are correctly generated before moving forward.
b. Other frameworks¶
Any junit.xml
input file would be accepted so other language users (e.g. java) can get this working for them as well.
Generating the badge¶
Now you can generate a badge similar to this one with the following command:
> genbadge tests
By default it assumes that
-
the input file can be found at
./reports/junit/junit.xml
. You can change this with the-i/--input-file
flag.-
can be used to denote<stdin>
: e.g.genbadge tests -i - < junit.xml
.
-
the output file will be at
./tests-badge.svg
. You can change it with the-o/--output-file
flag-
can be used to denote<stdout>
: e.g.genbadge tests -o - > badge.svg
.
-
the badge name (left-hand side text) is tests. You can change it with the
-n/--name
flag or clear it with-n ""
(but keep the empty space). Alternatively if you want to completely remove the left-hand side of the badge you can use--noname
. -
the badge should be generated using
shields.io
(requires an internet connection). If you prefer you can use-l/--local
to use the included SVG file template (less mature but seems to work)
In addition to generating the badge, executing the command will also display some details about the parsed file is you use the verbose -v
flag:
Test statistics parsed successfully from '(...)/reports/junit/junit.xml'
- Nb tests: Total (6) = Success (2) + Skipped (1) + Failed (2) + Errors (1)
- Success percentage: 40.00% (2 / 5) (Skipped tests are excluded)
SUCCESS - Tests badge created: '(...)/tests-badge.svg'
Note that without the verbose flag, only the last line of this message is displayed. You can disable it entirely using the silent flag -s
.
The resulting badge will by default look like this: [tests | 2/5]
where 2 is the number of tests that have run successfully, and 5 is the total number of tests minus the number of skipped tests. When all tests pass with success, the badge simply shows the number of tests: [tests | 5]
. The success percentage, defined as this ratio multiplied by 100, is displayed and can be further used to fail on threshold, see below.
Finally, the color of the badge depends on the success percentage.
- Less than 50%: red
- less than 75%: orange
- less than 90%: green
- higher: bright green
Using the badge¶
To include the resulting badge in your documentation and make it point to the generated report.html
, you can for example use the following markdown:
[![Tests Status](./reports/junit/junit-badge.svg?dummy=8484744)](./reports/junit/report.html)
Note that the query part of the image url ?dummy=8484744
is a trick so that the github pages web server does not try to add an extra cache layer to the badge. Maybe this is not useful anymore with new versions of github, if you know the answer let me know !
Security concerns
Test reports might contain secrets (keys, env variables, OS user names containing employee numbers, etc.), so always review them carefully before publishing them !
Failing on threshold¶
You might wish the command to fail if the success percentage is not high enough.
This may be done using the -t/--threshold
flag:
> genbadge tests -t 90
will fail and return an exit code of 1
if the success percentage is strictly lower than 90%.
The success percentage is defined as the number of tests that have run successfully, divided by the total number of tests minus the number of skipped tests, times 100. So for 6 tests run, if 2 tests ran successfully and 1 was skipped then the success percentage is 2 / (6 - 1) * 100
which gives 40%
.
2. Coverage badge¶
Prerequisite: a cov report¶
a. coverage
¶
If you use coverage
, you can use some options to generate reports:
-
with
coverage report
the coverage statistics are displayed in the console. This is not required but might be useful to debug if the xml generation fails. -
with
coverage xml
an XML-format report is generated. This is the file that we'll need to generate the badge. -
with
coverage html
a detailed HTML report (a folder) is generated. This is not required to generate the badge, but you might wish to use it so that users navigate to it when they will click on your badge.
Let's run this in your project:
> coverage report
> coverage xml
> coverage html
You can check that the coverage file and html report folder are correctly generated before moving forward.
b. Other frameworks¶
Any coverage.xml
input file would be accepted so other language users (e.g. java) can get this working for them as well.
Generating the badge¶
Now you can generate a badge similar to this one with the following command:
> genbadge coverage
By default it assumes that
-
the input file can be found at
./reports/coverage/coverage.xml
. You can change this with the-i/--input-file
flag.-
can be used to denote<stdin>
: e.g.genbadge coverage -i - < coverage.xml
.
-
the output file will be at
./coverage-badge.svg
. You can change it with the-o/--output-file
flag-
can be used to denote<stdout>
: e.g.genbadge coverage -o - > badge.svg
.
-
the badge name (left-hand side text) is coverage. You can change it with the
-n/--name
flag or clear it with-n ""
(but keep the empty space). Alternatively if you want to completely remove the left-hand side of the badge you can use--noname
. -
the badge should be generated using
shields.io
(requires an internet connection). If you prefer you can use-l/--local
to use the included SVG file template (less mature but seems to work)
In addition to generating the badge, executing the command will also display some details about the parsed file is you use the verbose -v
flag:
Coverage results parsed successfully from '(...)/reports/coverage/coverage.xml'
- Branch coverage: 5.56% (1/18)
- Line coverage: 17.81% (13/73)
- Total coverage: 15.38% ((1+13)/(18+73))
SUCCESS - Coverage badge created: '(...)/coverage-badge.svg'
Note that without the verbose flag, only the last line of this message is displayed. You can disable it entirely using the silent flag -s
.
The resulting badge will by default look like this: [coverage | 98.1%]
where 98.1 is the total coverage, obtained from the branch and line coverages using the formula (nb_lines_covered + nb_branches_covered) / (nb_lines / nb_branches)
and multiplying this by 100.
Finally, the color of the badge depends on the success percentage.
- Less than 50%: red
- less than 75%: orange
- less than 90%: green
- higher: bright green
Using the badge¶
To include the resulting badge in your documentation and make it point to the generated HTML report, you can for example use the following markdown:
[![Coverage Status](./reports/coverage/coverage-badge.svg?dummy=8484744)](./reports/coverage/index.html)
Note that the query part of the image url ?dummy=8484744
is a trick so that the github pages web server does not try to add an extra cache layer to the badge. Maybe this is not useful anymore with new versions of github, if you know the answer let me know !
3. Flake8 badge¶
Prerequisite: a flake8 report¶
If you use flake8
, you can use some options to generate reports:
-
with
--statistics
, the number of issues grouped by code (e.g.E201
) is consolidated and printed to std out. You can redirect this to a file namedflake8stats.txt
using--tee --output-file flake8stats.txt
. This is the file that we'll need to generate the badge. Note that--tee
is to continue to see the report on the console, this is optional. -
with
--format=html --htmldir
a detailed HTML report (a folder) is generated. This is not required to generate the badge, but you might wish to use it so that users navigate to it when they will click on your badge.
Let's run this in your project. We use --exit-zero
so that the commands always returns with exit code 0 even if problems are found.
> flake8 <src_folder> --exit-zero --format=html --htmldir ./reports/flake8 --statistics --tee --output-file flake8stats.txt
1 B014 Redundant exception types in `except (IOError, OSError):`. Write `except OSError:`, which catches exactly the same exceptions.
7 C801 Copyright notice not present.
1 E122 continuation line missing indentation or outdented
1 E303 too many blank lines (3)
...
You can check that the statistics file and html report folder are correctly generated before moving forward.
Generating the badge¶
Now you can generate a badge similar to this one with the following command:
> genbadge flake8
By default it assumes that
-
the input file can be found at
./reports/flake8/flake8stats.txt
. You can change this with the-i/--input-file
flag.-
can be used to denote<stdin>
: e.g.genbadge flake8 -i - < flake8stats.txt
.
-
the output file will be at
./flake8-badge.svg
. You can change it with the-o/--output-file
flag-
can be used to denote<stdout>
: e.g.genbadge flake8 -o - > badge.svg
.
-
the badge name (left-hand side text) is flake8. You can change it with the
-n/--name
flag or clear it with-n ""
(but keep the empty space). Alternatively if you want to completely remove the left-hand side of the badge you can use--noname
. -
the badge should be generated using
shields.io
(requires an internet connection). If you prefer you can use-l/--local
to use the included SVG file template (less mature but seems to work)
In addition to generating the badge, executing the command will also display some details about the parsed file is you use the verbose -v
flag:
Flake8 statistics parsed successfully from '(...)/reports/flake8/flake8stats.txt'
- Total (20) = Critical (6) + Warning (9) + Info (5)
SUCCESS - Flake8 badge created: '(...)/flake8-badge.svg'
Note that without the verbose flag, only the last line of this message is displayed. You can disable it entirely using the silent flag -s
.
The resulting badge will by default look like this: [flake8 | 6 C, 0 W, 5 I]
where 6, 0, 5 denote the number of critical issues, warnings, and information messages respectively. These severity levels are determined by the flake8-html
plugin so as to match the colors in the HTML report.
Finally, the color of the badge depends on the number of issues at each severity level.
- at least a critical issue (severity 1): red
- at least a warning (severity 2): orange
- at least an info (severity 3): green
- no issue at all: bright green
Using the badge¶
To include the resulting badge in your documentation and make it point to the generated HTML report, you can for example use the following markdown:
[![Flake8 Status](./reports/flake8/flake8-badge.svg?dummy=8484744)](./reports/flake8/index.html)
Note that the query part of the image url ?dummy=8484744
is a trick so that the github pages web server does not try to add an extra cache layer to the badge. Maybe this is not useful anymore with new versions of github, if you know the answer let me know !
4. Low-level API¶
You can create a badge with the Badge
class.
from genbadge import Badge
b = Badge(left_txt="foo", right_txt="bar", color="green")
print(b)
yields
[ foo | bar ] color: green
By default no svg is generated: this is a purely abstract badge. You can make it a real badge with the following code:
b.write_to("tmp_badge.svg", use_shields=False)
Note the optional use_shields
boolean flag that is used to switch between querying shields.io
(True
, default) or using a local SVG file template (False
, but maybe less bullet-proof).
See Also¶
Other badge generation projects exist:
coverage-badge
, see in particular this discussionflake8-svg-badge
that seems abandoned ?
Others¶
Do you like this library ? You might also like my other python libraries
Want to contribute ?¶
Details on the github page: https://github.com/smarie/python-genbadge