🔥
|
This software is under development and not yet usable. |
This program is the core module of Hostsharing's billing system. It’s based on snapshot input CSV-files, supplied by other modules and creates a set of output-files like accounting records and invoices. These outputs are processed by subsequent steps, like mailing the invoices to the customers.
Executions are idempotent and therefore repeatable: As long as the parameters and input files are the same, each run will produce exactly the same output.
The input-CSV-files, supplied by other modules are:
-
customer.csv
- containing customer data like billing-contact and payment mode -
multiple
*-billing-items.csv
- containing items to be invoiced from multiple sources -
vat-groups.csv
- specifies
For each run it creates a set of output files through Velocity templates:
-
accounting-records.csv
- accounting records including VAT-specific account numbers to be further processed by the accounting system -
invoices in several formats like for emails and PDF-generation (not implemented yet)
-
sepa.csv
- contains records for direct debiting -
…
The root-package of this program org.hostsharing.hsadmin.billing.core
contains the main program.
The main program orchestrates the following modules.
It contains the following sub-packages:
domain
-
Types describing the domain model.
reader
-
Classes and functions which read and parse the input CSV-file and convert these into domain-objects.
invoicing
-
Actual "calculation" of the invoices using the domain objects from the
reader
. The output is an internal presentation of the invoices. generator
-
These generators take the internal presentation of the invoices from the
invoicing
module and produce output domain objects for further processing by thewriter
writer
-
Functions which convert the generated domain objects to be used as contexts in Velocity templates which then are used to generate the output files.
lib
-
Types functions which can be used in all other modules.
To see all available build tasks, run:
./gradlew tasks --all
The Gradle task dependency plugin tiTree can be used to list all gradlew
tasks with their dependencies.
For example to see all dependencies of the gradlew build
task, run:
$ ./gradlew tiTree build
To get a dependency graph of all used libraries, run:
$ /gradlew app:dependencies
A dependabot for automatic dependency update checking of this project is running on its github repo.
The general formatting of files is defined in .editorconfig
, these settings should automatically be picked up by most code editors and IDSs.
Also, ktlint is installed and configured. To check code style, run:
$ ./gradlew ktlint
This task also bound to "gradle check".
To automatically fix code style deviations, use:
$ ./gradlew ktlintFormat
For checking code complexity detekt is configured:
$ ./gradlew detekt
This command will check for rule violations and create a report.
The configuration can be found in app/config/detekt/config.yml.
For more information see detekt project on Github.
For unit-testing, JUnit 5 (Jupiter)_ is used along with assertk, a Kotlin version of assertj as a check task for gradle.
To execute the unit-tests, run:
$ ./gradlew test
For writing unit-tests consider the BRIEF rules from BDD:
- Business language
-
enables collaboration and feedback
- Real data
-
helps to discover white spots in requirements
- Intention revealing
-
is a way to describe the tests by focusing on what we wanted to achieve and not on how
- Essential
-
include only relevant details in the scenario
- Focused
-
the scenarios should illustrate a single rule only Brief — keep scenarios short
For prettier output of test results, a testlogger is configured.
Find the configuration in ./app/build.gradle under testlogger
.
On Windows, to get a proper output, you need to change the codepage before running gradle:
chcp 65001
To verify a specified test code coverage minimum, jacoco is configured.
The verification is a dependent of gradlew check
and can be run separately with:
$ ./gradlew jacocoTestCodeCoverageVerification
A coverage report (./app/build/reports/jacoco/index.html]) can be generated with:
$ ./gradlew jacocoTestReport
Find the configuration in ./app/build.gradle
To check the quality of the assertions in the unit-tests, pitest is used as a mutation testing-tool.
The mutation-tests can be executed with:
$ ./gradlew pitest
This creates a report comprising line- and mutation-coverage of the unit-tests.
If the "mutant-kill rate" falls below a configured limit, the pitest-task will fail;
in that case, please improve the unit-tests.
The limits are configured in app/build.gradle
.
Please increase the limit according to the level we have reached, once we become better;
about 2 percent points below the level we have actually reached, is a good measure.
🔥
|
After a successful run, you can see percentage which actually counts for the limit. The percentage shown in the report HTML-file seems to be calculated differently and is usually a bit higher. |
Similar to the problem mentioned above (see chapter Test Code Coverage), some Kotlin features generate code which our tests won’t cover and should not cover because we don’t want to test the Kotlin compiler. Unfortunately pitest does not know about this fact and is going to mutate this code as well which leads to false positives. Most of these issues could only be fixed jointly by the Kotlin-compiler and pitest development teams, as mentioned in this open Kotlin-compiler issue.
There is some automatic verification of architecture rules using ArchUnit in the unit test ArchitectureTest
.
See there for more information, especially about the git branch archunit-rule-validation
and verifying the rules themselves.
Technically this is a mal unit-test, thus run with:
$ ./gradlew test