diff --git a/.github/auto_assign.yml b/.github/auto_assign.yml new file mode 100644 index 0000000..5f6be8a --- /dev/null +++ b/.github/auto_assign.yml @@ -0,0 +1,10 @@ +addReviewers: false +addAssignees: true + +assignees: + - uhafner + +skipKeywords: + - wip + +numberOfAssignees: 0 diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..6fe8aae --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,33 @@ +version: 2 +updates: + - package-ecosystem: maven + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 + commit-message: + prefix: "" + ignore: + - dependency-name: org.eclipse.collections:eclipse-collections + versions: + - ">= 10.a" + - dependency-name: org.eclipse.collections:eclipse-collections-api + versions: + - ">= 10.a" + - dependency-name: net.javacrumbs.json-unit:json-unit-assertj + versions: + - ">= 3.0.0" + + - package-ecosystem: "github-actions" + directory: "/" + commit-message: + prefix: "" + schedule: + interval: "daily" + + - package-ecosystem: "npm" + directory: "/" + commit-message: + prefix: "" + schedule: + interval: "daily" diff --git a/.github/labels.yml b/.github/labels.yml new file mode 100644 index 0000000..a070a39 --- /dev/null +++ b/.github/labels.yml @@ -0,0 +1,27 @@ +- name: bug + description: Bugs or performance problems + color: CC0000 +- name: dependencies + description: Update of dependencies + color: 0366d6 +- name: feature + color: a4c6fb + description: New features +- name: enhancement + description: Enhancement of existing functionality + color: 94a6eb +- name: deprecated + description: Deprecating API + color: f4c21d +- name: removed + description: Removing API + color: e4b21d +- name: tests + description: Enhancement of tests + color: 30cc62 +- name: documentation + description: Enhancement of documentation + color: bfafea +- name: internal + description: Internal changes without user or API impact + color: e6e6e6 diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..ae7cb33 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,51 @@ +name-template: 'v$RESOLVED_VERSION 🎁' +tag-template: 'v$RESOLVED_VERSION' + +template: | + $CHANGES + +# Emoji reference: https://gitmoji.carloscuesta.me/ +categories: + - title: 💥 Removed + label: removed + - title: ⚠️ Deprecated + label: deprecated + - title: 🚀 New features + labels: + - feature + - title: ✨ Improvements + labels: + - enhancement + - title: 🐛 Bug Fixes + labels: + - bug + - fix + - bugfix + - regression + - title: 📝 Documentation updates + label: documentation + - title: 📦 Dependency updates + label: dependencies + - title: 🔧 Internal changes + label: internal + - title: 🚦 Tests + labels: + - test + - tests + +version-resolver: + major: + labels: + - 'removed' + minor: + labels: + - 'feature' + - 'enhancement' + - 'deprecated' + patch: + labels: + - 'dependencies' + - 'documentation' + - 'tests' + - 'internal' + default: minor diff --git a/.github/workflows/assign-pr.yml b/.github/workflows/assign-pr.yml new file mode 100644 index 0000000..4da9319 --- /dev/null +++ b/.github/workflows/assign-pr.yml @@ -0,0 +1,12 @@ +name: 'Auto Assign PR' + +on: pull_request_target + +jobs: + assign-pr: + name: 'Auto Assign PR' + runs-on: ubuntu-latest + steps: + - uses: kentaro-m/auto-assign-action@v1.2.5 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/autograding.yml b/.github/workflows/autograding.yml new file mode 100644 index 0000000..b3a0ca2 --- /dev/null +++ b/.github/workflows/autograding.yml @@ -0,0 +1,124 @@ +name: 'Autograding PR' + +on: + pull_request: + +jobs: + build: + + runs-on: [ubuntu-latest] + name: Build, test and autograde on Ubuntu + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 21 + check-latest: true + cache: 'maven' + - name: Set up Maven + uses: stCarolas/setup-maven@v4.5 + with: + maven-version: 3.9.5 + - name: Build with Maven + env: + BROWSER: chrome-container + run: mvn -V --color always -ntp clean verify --file pom.xml '-Djenkins.test.timeout=5000' '-Dgpg.skip' -Ppit | tee maven.log + - name: Extract pull request number + uses: jwalton/gh-find-current-pr@v1 + id: pr + - name: Run Autograding + uses: uhafner/autograding-github-action@v3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + pr-number: ${{ steps.pr.outputs.number }} + checks-name: 'Quality Checks' + config: > + { + "tests": { + "tools": [ + { + "id": "test", + "name": "Unittests", + "pattern": "**/target/*-reports/TEST*.xml" + } + ], + "name": "JUnit", + "passedImpact": 0, + "skippedImpact": -1, + "failureImpact": -5, + "maxScore": 100 + }, + "analysis": { + "name": "Warnings", + "id": "warnings", + "tools": [ + { + "id": "checkstyle", + "name": "CheckStyle", + "pattern": "**/target/checkstyle-result.xml" + }, + { + "id": "pmd", + "name": "PMD", + "pattern": "**/target/pmd.xml" + }, + { + "id": "error-prone", + "name": "Error Prone", + "pattern": "**/maven.log" + }, + { + "id": "spotbugs", + "name": "SpotBugs", + "sourcePath": "src/main/java", + "pattern": "**/target/spotbugsXml.xml" + } + + ], + "errorImpact": -1, + "highImpact": -1, + "normalImpact": -1, + "lowImpact": -1, + "maxScore": 100 + }, + "coverage": [ + { + "tools": [ + { + "id": "jacoco", + "name": "Line Coverage", + "metric": "line", + "sourcePath": "src/main/java", + "pattern": "**/target/site/jacoco/jacoco.xml" + }, + { + "id": "jacoco", + "name": "Branch Coverage", + "metric": "branch", + "sourcePath": "src/main/java", + "pattern": "**/target/site/jacoco/jacoco.xml" + } + ], + "name": "JaCoCo", + "maxScore": 100, + "missedPercentageImpact": -1 + }, + { + "tools": [ + { + "id": "pit", + "name": "Mutation Coverage", + "metric": "mutation", + "sourcePath": "src/main/java", + "pattern": "**/target/pit-reports/mutations.xml" + } + ], + "name": "PIT", + "maxScore": 100, + "missedPercentageImpact": -1 + } + ] + } diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 0000000..061beb8 --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,29 @@ +name: CD + +on: + push: + branches: + - main + +jobs: + build: + name: Build and deploy to Docker hub + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + check-latest: true + cache: 'maven' + - name: Set up Maven + uses: stCarolas/setup-maven@v4.5 + with: + maven-version: 3.9.5 + - name: Build and deploy + env: + DOCKER_IO_USERNAME: ${{ secrets.DOCKER_IO_USERNAME }} + DOCKER_IO_PASSWORD: ${{ secrets.DOCKER_IO_PASSWORD }} + run: mvn -ntp clean install diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..bbd329c --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,72 @@ +name: "CodeQL" + +on: + push: + branches: + - master + - main + pull_request: + branches: + - master + - main + schedule: + - cron: "32 3 * * 0" + +jobs: + analyze: + name: Analyze with CodeQL + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ java ] + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 21 + cache: maven + + - name: Set up Maven + uses: stCarolas/setup-maven@v4.5 + with: + maven-version: 3.9.6 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + queries: +security-and-quality + + - name: Build with Maven + run: mvn -V --color always -ntp clean verify --file pom.xml -Pskip + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + upload: false + output: sarif-results + category: "/language:${{ matrix.language }}" + + - name: Filter SARIF results + uses: advanced-security/filter-sarif@v1 + with: + patterns: | + -**/*Assert* + input: sarif-results/${{ matrix.language }}.sarif + output: sarif-results/${{ matrix.language }}.sarif + + - name: Upload SARIF results + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: sarif-results/${{ matrix.language }}.sarif diff --git a/.github/workflows/dogfood.yml b/.github/workflows/dogfood.yml new file mode 100644 index 0000000..e404d86 --- /dev/null +++ b/.github/workflows/dogfood.yml @@ -0,0 +1,309 @@ +name: Eat your own dog food + +on: + workflow_run: + workflows: ["CD"] + types: + - completed + +jobs: + grade-test-data: + name: Run autograding with test data + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + check-latest: true + cache: 'maven' + - name: Set up Maven + uses: stCarolas/setup-maven@v4.5 + with: + maven-version: 3.9.5 + - name: Run Autograding with test data + uses: uhafner/autograding-github-action@main + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + checks-name: "Autograding with Test Data" + config: > + { + "tests": { + "tools": [ + { + "id": "test", + "name": "Unittests", + "pattern": "**/src/test/resources/**/TEST*.xml" + } + ], + "name": "JUnit", + "passedImpact": 10, + "skippedImpact": -1, + "failureImpact": -5, + "maxScore": 100 + }, + "analysis": [ + { + "name": "Style", + "id": "style", + "tools": [ + { + "id": "checkstyle", + "name": "CheckStyle", + "pattern": "**/src/test/resources/**/checkstyle*.xml" + }, + { + "id": "pmd", + "name": "PMD", + "pattern": "**/src/test/resources/**/pmd*.xml" + } + ], + "errorImpact": 1, + "highImpact": 2, + "normalImpact": 3, + "lowImpact": 4, + "maxScore": 100 + }, + { + "name": "Bugs", + "id": "bugs", + "icon": "bug", + "tools": [ + { + "id": "spotbugs", + "name": "SpotBugs", + "pattern": "**/src/test/resources/**/spotbugs*.xml" + } + ], + "errorImpact": -11, + "highImpact": -12, + "normalImpact": -13, + "lowImpact": -14, + "maxScore": 100 + } + ], + "coverage": [ + { + "tools": [ + { + "id": "jacoco", + "name": "Line Coverage", + "metric": "line", + "pattern": "**/src/test/resources/**/jacoco.xml" + }, + { + "id": "jacoco", + "name": "Branch Coverage", + "metric": "branch", + "pattern": "**/src/test/resources/**/jacoco.xml" + } + ], + "name": "JaCoCo", + "maxScore": 100, + "coveredPercentageImpact": 1, + "missedPercentageImpact": -1 + }, + { + "tools": [ + { + "id": "pit", + "name": "Mutation Coverage", + "metric": "mutation", + "pattern": "**/src/test/resources/**/mutations.xml" + } + ], + "name": "PIT", + "maxScore": 100, + "coveredPercentageImpact": 1, + "missedPercentageImpact": -1 + } + ] + } + grade-github-action: + name: Run autograding for the GitHub Autograding Action + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + check-latest: true + cache: 'maven' + - name: Set up Maven + uses: stCarolas/setup-maven@v4.5 + with: + maven-version: 3.9.5 + - name: Build + run: mvn -ntp clean verify -Ppit + - name: Run Autograding + uses: uhafner/autograding-github-action@main + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + checks-name: "Autograding GitHub Action" + config: > + { + "tests": { + "tools": [ + { + "id": "test", + "name": "Unittests", + "pattern": "**/target/*-reports/TEST*.xml" + } + ], + "name": "JUnit", + "passedImpact": 0, + "skippedImpact": -1, + "failureImpact": -5, + "maxScore": 100 + }, + "analysis": [ + { + "name": "Style", + "id": "style", + "tools": [ + { + "id": "checkstyle", + "name": "CheckStyle", + "pattern": "**/target/checkstyle-result.xml" + }, + { + "id": "pmd", + "name": "PMD", + "pattern": "**/target/pmd.xml" + } + ], + "errorImpact": 1, + "highImpact": 2, + "normalImpact": 3, + "lowImpact": 4, + "maxScore": 100 + }, + { + "name": "Bugs", + "id": "bugs", + "icon": "bug", + "tools": [ + { + "id": "spotbugs", + "name": "SpotBugs", + "sourcePath": "src/main/java", + "pattern": "**/target/spotbugsXml.xml" + } + ], + "errorImpact": -11, + "highImpact": -12, + "normalImpact": -13, + "lowImpact": -14, + "maxScore": 100 + } + ], + "coverage": [ + { + "tools": [ + { + "id": "jacoco", + "sourcePath": "src/main/java", + "name": "Line Coverage", + "metric": "line", + "pattern": "**/target/site/jacoco/jacoco.xml" + }, + { + "id": "jacoco", + "sourcePath": "src/main/java", + "name": "Branch Coverage", + "metric": "branch", + "pattern": "**/target/site/jacoco/jacoco.xml" + } + ], + "name": "JaCoCo", + "maxScore": 100, + "coveredPercentageImpact": 1, + "missedPercentageImpact": -1 + }, + { + "tools": [ + { + "id": "pit", + "name": "Mutation Coverage", + "metric": "mutation", + "sourcePath": "src/main/java", + "pattern": "**/target/pit-reports/mutations.xml" + } + ], + "name": "PIT", + "maxScore": 100, + "coveredPercentageImpact": 1, + "missedPercentageImpact": -1 + } + ] + } + - name: Write metrics to GitHub output + id: metrics + run: | + cat metrics.env >> "${GITHUB_OUTPUT}" + mkdir -p badges + - name: Generate the badge SVG image for the line coverage + uses: emibcn/badge-action@v2.0.2 + with: + label: 'Lines' + status: ${{ steps.metrics.outputs.line }}% + color: 'green' + path: badges/line-coverage.svg + - name: Generate the badge SVG image for the branch coverage + uses: emibcn/badge-action@v2.0.2 + with: + label: 'Branches' + status: ${{ steps.metrics.outputs.branch }}% + color: 'green' + path: badges/branch-coverage.svg + - name: Generate the badge SVG image for the mutation coverage + uses: emibcn/badge-action@v2.0.2 + with: + label: 'Mutations' + status: ${{ steps.metrics.outputs.mutation }}% + color: 'green' + path: badges/mutation-coverage.svg + - name: Generate the badge SVG image for the style warnings + uses: emibcn/badge-action@v2.0.2 + with: + label: 'Warnings' + status: ${{ steps.metrics.outputs.style }} + color: 'orange' + path: badges/style-warnings.svg + - name: Generate the badge SVG image for the potential bugs + uses: emibcn/badge-action@v2.0.2 + with: + label: 'Bugs' + status: ${{ steps.metrics.outputs.bugs }} + color: 'red' + path: badges/bugs.svg + - name: Generate progress SVG + id: chart + uses: robiningelbrecht/apache-echarts-action@v1.1.0 + with: + width: 256 + height: 256 + pass-options-as: string + chart-option: '{ "tooltip": { "trigger": "item", "formatter": "null of null" }, "series": [ { "type": "pie", "radius": [ "70%", "100%" ], "avoidLabelOverlap": false, "color": [ "#1ea64b", "#D0D0D0 " ], "hoverAnimation": false, "label": { "show": true, "position": "center", "fontSize": "38", "fontWeight": "bold", "color": "#000", "formatter": "92%" }, "labelLine": { "normal": { "show": false } }, "data": [ { "value": 92, "name": "Filled" }, { "value": 8, "name": "NotFilled" } ] } ] }' + - name: Save generated SVG + run: | + cat < badges/progress.svg + ${{ steps.chart.outputs.svg }} + EOF + - name: Commit updated badges + continue-on-error: true + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add badges/*.svg + git commit -m "Update badges with results from latest autograding" || true + - name: Push updated badges to GitHub repository + uses: ad-m/github-push-action@master + if: ${{ success() }} + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: main diff --git a/.github/workflows/enforce-labels.yml b/.github/workflows/enforce-labels.yml new file mode 100644 index 0000000..56b84cc --- /dev/null +++ b/.github/workflows/enforce-labels.yml @@ -0,0 +1,18 @@ +name: Enforce PR labels +on: + pull_request: + types: [opened, labeled, unlabeled, synchronize] +jobs: + enforce-labels: + name: Enforce PR labels + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: mheap/github-action-required-labels@v5 + with: + mode: minimum + count: 1 + labels: "bug,feature,enhancement,breaking,tests,documentation,internal,dependencies" + message: "Maintainer needs to assign at least one label before merge" diff --git a/.github/workflows/run-release-drafter.yml b/.github/workflows/run-release-drafter.yml new file mode 100644 index 0000000..f9403e7 --- /dev/null +++ b/.github/workflows/run-release-drafter.yml @@ -0,0 +1,16 @@ +name: 'Invoke Release Drafter' + +on: + push: + branches: + - master + - main + +jobs: + update-release-draft: + name: 'Update Release Draft' + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v5.25.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/sync-labels.yml b/.github/workflows/sync-labels.yml new file mode 100644 index 0000000..786bb2e --- /dev/null +++ b/.github/workflows/sync-labels.yml @@ -0,0 +1,21 @@ +name: Sync labels +on: + push: + branches: + - master + - main + paths: + - .github/labels.yml + - .github/workflows/sync-labels.yml + +jobs: + snyc-labels: + name: Sync labels + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: micnncim/action-label-syncer@v1.3.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + manifest: .github/labels.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9ec2d87 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +node +node_modules +target +*.iml +.classpath +.project +.settings +pom.xml.versionsBackup +pom.xml.releaseBackup +release.properties +.DS_Store +.idea +/package-lock.json +metrics.env diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..852ac2f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Dr. Ullrich Hafner + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..331f2f7 --- /dev/null +++ b/README.md @@ -0,0 +1,337 @@ +# Autograding GitHub Action + +[![GitHub Actions](https://github.com/uhafner/autograding-github-action/workflows/CD/badge.svg)](https://github.com/uhafner/autograding-github-action/actions/workflows/cd.yml) +[![CodeQL](https://github.com/uhafner/autograding-github-action/workflows/CodeQL/badge.svg)](https://github.com/uhafner/autograding-github-action/actions/workflows/codeql.yml) +[![Line Coverage](https://raw.githubusercontent.com/uhafner/autograding-github-action/main/badges/line-coverage.svg)](https://github.com/uhafner/autograding-github-action/actions/workflows/dogfood.yml) +[![Branch Coverage](https://raw.githubusercontent.com/uhafner/autograding-github-action/main/badges/branch-coverage.svg)](https://github.com/uhafner/autograding-github-action/actions/workflows/dogfood.yml) +[![Mutation Coverage](https://raw.githubusercontent.com/uhafner/autograding-github-action/main/badges/mutation-coverage.svg)](https://github.com/uhafner/autograding-github-action/actions/workflows/dogfood.yml) +[![Style Warnings](https://raw.githubusercontent.com/uhafner/autograding-github-action/main/badges/style-warnings.svg)](https://github.com/uhafner/autograding-github-action/actions/workflows/dogfood.yml) +[![Potential Bugs](https://raw.githubusercontent.com/uhafner/autograding-github-action/main/badges/bugs.svg)](https://github.com/uhafner/autograding-github-action/actions/workflows/dogfood.yml) + +This GitHub action autogrades projects based on a configurable set of metrics and gives feedback on pull requests (or single commits) in GitHub. I use this action to automatically grade student projects in my lectures at the Munich University of Applied Sciences. + +You can see the results of this action in an [example pull request](https://github.com/uhafner/autograding-github-action/pull/311) and the associated [GitHub Checks output](https://github.com/uhafner/autograding-github-action/runs/19411191545). Another real-live example is visible in the [pull request](https://github.com/uhafner/java2-assignment1/pull/31) and [checks result](https://github.com/uhafner/java2-assignment1/runs/19411468263) of a fake student project. + +![Pull request comment](images/pr-comment.png) + +Please have a look at my [companion coding style](https://github.com/uhafner/codingstyle) and [Maven parent POM](https://github.com/uhafner/codingstyle-pom) to see how to create Java projects that can be graded using this GitHub action. If you are hosting your project on GitLab, then you might be interested in my [identical GitLab action](https://github.com/uhafner/autograding-gitlab-action) as well. + +Both actions are inspired by my Jenkins plugins: +- [Jenkins Warnings plugin](https://github.com/jenkinsci/warnings-ng-plugin) +- [Jenkins Coverage plugin](https://github.com/jenkinsci/coverage-plugin) +- [Jenkins Autograding plugin](https://github.com/jenkinsci/autograding-plugin) + +They work in the same way but are much more powerful and flexible and show the results additionally in Jenkins' UI. + +Please note that the action works on report files that are generated by other tools. It does not run the tests or static analysis tools itself. You need to run these tools in a previous step of your workflow. See the example below for details. This has the advantage that you can use a tooling you are already familiar with. So the action will run for any programming language that can generate the required report files. There are already more than [one hundred analysis formats](https://github.com/jenkinsci/analysis-model/blob/main/SUPPORTED-FORMATS.md) supported. Code and mutation coverage reports can use the JaCoCo, Cobertura and PIT formats, see the [coverage model](https:://github.com/jenkinsci/coverage-model) for details. + +# GitHub Checks + +The details output of the action is shown in the GitHub Checks tab of the pull request: + +![GitHub checks result](images/details.png) + +# Configuration + +The individual metrics can be configured by defining an appropriate `CONFIG` property (in JSON format) in your GitHub workflow: + +```yaml +name: Autograde project + +on: + push + +jobs: + grade-project: + name: Autograde project + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '21' + check-latest: true + cache: 'maven' + - name: Set up Maven + uses: stCarolas/setup-maven@v4.5 + with: + maven-version: 3.9.5 + - name: Build # (compile, test with code and mutation coverage, and run static analysis) + run: mvn -ntp clean verify -Ppit + - name: Extract pull request number # (commenting on the pull request requires the PR number) + uses: jwalton/gh-find-current-pr@v1 + id: pr + - name: Run Autograding + uses: uhafner/autograding-github-action@v3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + pr-number: ${{ steps.pr.outputs.number }} + checks-name: "Autograding GitHub Action" + config: > # Override default configuration: just grade the test results + { + "tests": { + "tools": [ + { + "id": "test", + "name": "Unittests", + "pattern": "**/target/*-reports/TEST*.xml" + } + ], + "name": "JUnit", + "skippedImpact": -1, + "failureImpact": -5, + "maxScore": 100 + } + } +``` + +Currently, you can select from the metrics shown in the following sections. Each metric can be configured individually. All of these configurations are composed in the same way: you can define a list of tools that are used to collect the data, a name and icon for the metric, and a maximum score. All tools need to provide a pattern where the autograding action can find the result files in the workspace (e.g., JUnit XML reports). Additionally, each tool needs to provide the parser ID of the tool so that the underlying model can find the correct parser to read the results. See [analysis model](https:://github.com/jenkinsci/analysis-model) and [coverage model](https:://github.com/jenkinsci/coverage-model) for the list of supported parsers. + +Additionally, you can define the impact of each result (e.g., a failed test, a missed line in coverage) on the final score. The impact is a positive or negative number and will be multiplied with the actual value of the measured items during the evaluation. Negative values will be subtracted from the maximum score to compute the final score. Positive values will be directly used as the final score. You can choose the type of impact that matches your needs best. + +## Test statistics (e.g., number of failed tests) + +![Test statistics](images/tests.png) + +This metric can be configured using a JSON object `tests`, see the example below for details: + +```json +{ + "tests": { + "tools": [ + { + "id": "test", + "name": "Unittests", + "pattern": "**/junit*.xml" + } + ], + "name": "JUnit", + "passedImpact": 10, + "skippedImpact": -1, + "failureImpact": -5, + "maxScore": 100 + } +} +``` + +You can either count passed tests as positive impact or failed tests as negative impact (or use a mix of both). For failed tests, the test error message and stack trace will be shown directly after the summary in the pull request. + +## Code or mutation coverage (e.g., line coverage percentage) + +![Code coverage summary](images/coverage.png) + +This metric can be configured using a JSON object `coverage`, see the example below for details: + +```json +{ + "coverage": [ + { + "tools": [ + { + "id": "jacoco", + "name": "Line Coverage", + "metric": "line", + "sourcePath": "src/main/java", + "pattern": "**/jacoco.xml" + }, + { + "id": "jacoco", + "name": "Branch Coverage", + "metric": "branch", + "sourcePath": "src/main/java", + "pattern": "**/jacoco.xml" + } + ], + "name": "JaCoCo", + "maxScore": 100, + "coveredPercentageImpact": 1, + "missedPercentageImpact": -1 + }, + { + "tools": [ + { + "id": "pit", + "name": "Mutation Coverage", + "metric": "mutation", + "sourcePath": "src/main/java", + "pattern": "**/mutations.xml" + } + ], + "name": "PIT", + "maxScore": 100, + "coveredPercentageImpact": 1, + "missedPercentageImpact": 0 + } + ] +} +``` + +You can either use the covered percentage as positive impact or the missed percentage as negative impact (a mix of both makes little sense but would work as well). Please make sure to define exactly a unique and supported metric for each tool. For example, JaCoCo provides `line` and `branch` coverage, so you need to define two tools for JaCoCo. PIT provides mutation coverage, so you need to define a tool for PIT that uses the metric `mutation`. + +Missed lines or branches as well as survived mutations will be shown as annotations in the pull request: + +![Code coverage annotations](images/coverage-annotations.png) +![Mutation coverage annotations](images/mutation-annotations.png) + + +## Static analysis (e.g., number of warnings) + +![Static analysis](images/analysis.png) + +This metric can be configured using a JSON object `analysis`, see the example above for details: + +```json +{ + "analysis": [ + { + "name": "Style", + "id": "style", + "tools": [ + { + "id": "checkstyle", + "name": "CheckStyle", + "pattern": "**/target/checkstyle-result.xml" + }, + { + "id": "pmd", + "name": "PMD", + "pattern": "**/target/pmd.xml" + } + ], + "errorImpact": 1, + "highImpact": 2, + "normalImpact": 3, + "lowImpact": 4, + "maxScore": 100 + }, + { + "name": "Bugs", + "id": "bugs", + "icon": "bug", + "tools": [ + { + "id": "spotbugs", + "name": "SpotBugs", + "sourcePath": "src/main/java", + "pattern": "**/target/spotbugsXml.xml" + } + ], + "errorImpact": -11, + "highImpact": -12, + "normalImpact": -13, + "lowImpact": -14, + "maxScore": 100 + } + ] +} +``` + +Normally, you would only use a negative impact for this metric: each warning (of a given severity) will reduce the final score by the specified amount. You can define the impact of each severity level individually. + +All warnings will be shown as annotations in the pull request: + +![Warning annotations](images/analysis-annotations.png ) + +## Action Parameters + +This action can be configured using the following parameters (see example above): +- ``github-token: ${{ secrets.GITHUB_TOKEN }}``: mandatory GitHub access token. +- ``config: "{...}"``: optional configuration, see sections above for details, or consult the [autograding-model](https://github.com/uhafner/autograding-model) project for the exact implementation. If not specified, a [default configuration](https://github.com/uhafner/autograding-model/blob/main/src/main/resources/default-config.json) will be used. +- ``pr-number: ${{ steps.pr.outputs.number }}``: optional number of the pull request. If not set, then just the checks will be published but not a pull request comment. +- ``checks-name: "Name of checks"``: optional name of GitHub checks (overwrites the default: "Autograding result"). +- ``skip-annotations: true``: Optional flag to skip the creation of annotations (for warnings and missed coverage). + +## Pull Request Comments + +The action writes a summary of the results to the pull request as well. Since the action cannot identify the correct pull request on its own, you need to provide the pull request as an action argument. + +```yaml + [... ] + + - name: Extract pull request number + uses: jwalton/gh-find-current-pr@v1 + id: pr + - name: Run Autograding + uses: uhafner/autograding-github-action@v3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + pr-number: ${{ steps.pr.outputs.number }} + checks-name: "Autograding GitHub Action" + config: {...} + + [... ] +``` + +Configuring the action in this way will produce an additional comment of the form: + +![Pull request comment](images/pr-comment.png) + +## Automatic Badge Creation + +[![Line Coverage](https://raw.githubusercontent.com/uhafner/autograding-github-action/main/badges/line-coverage.svg)](https://github.com/uhafner/autograding-github-action/actions/workflows/dogfood.yml) +[![Branch Coverage](https://raw.githubusercontent.com/uhafner/autograding-github-action/main/badges/branch-coverage.svg)](https://github.com/uhafner/autograding-github-action/actions/workflows/dogfood.yml) +[![Mutation Coverage](https://raw.githubusercontent.com/uhafner/autograding-github-action/main/badges/mutation-coverage.svg)](https://github.com/uhafner/autograding-github-action/actions/workflows/dogfood.yml) +[![Style Warnings](https://raw.githubusercontent.com/uhafner/autograding-github-action/main/badges/style-warnings.svg)](https://github.com/uhafner/autograding-github-action/actions/workflows/dogfood.yml) +[![Potential Bugs](https://raw.githubusercontent.com/uhafner/autograding-github-action/main/badges/bugs.svg)](https://github.com/uhafner/autograding-github-action/actions/workflows/dogfood.yml) + + +The results of the action can be used to create various badges that show the current status of the project. The action writes the results of the action to a file called `metrics.env` in the workspace. This file can be used to create badges using the [GitHub Badge Action](https://github.com/marketplace/actions/badge-action). The following snippet shows how to create severage badges for your project, the full example is visible in [my autograding workflow](https://raw.githubusercontent.com/uhafner/autograding-github-action/main/.github/workflows/dogfood.yml). + +```yaml + [... Autograding, see above ... ] + - name: Write metrics to GitHub output + id: metrics + run: | + cat metrics.env >> "${GITHUB_OUTPUT}" + mkdir -p badges + - name: Generate the badge SVG image for the line coverage + uses: emibcn/badge-action@v2.0.2 + with: + label: 'Line coverage' + status: ${{ steps.metrics.outputs.line }}% + color: 'green' + path: badges/line-coverage.svg + - name: Generate the badge SVG image for the branch coverage + uses: emibcn/badge-action@v2.0.2 + with: + label: 'Branch coverage' + status: ${{ steps.metrics.outputs.branch }}% + color: 'green' + path: badges/branch-coverage.svg + - name: Generate the badge SVG image for the mutation coverage + uses: emibcn/badge-action@v2.0.2 + with: + label: 'Mutation coverage' + status: ${{ steps.metrics.outputs.mutation }}% + color: 'green' + path: badges/mutation-coverage.svg + - name: Generate the badge SVG image for the style warnings + uses: emibcn/badge-action@v2.0.2 + with: + label: 'Style warnings' + status: ${{ steps.metrics.outputs.style }} + color: 'orange' + path: badges/style-warnings.svg + - name: Generate the badge SVG image for the potential bugs + uses: emibcn/badge-action@v2.0.2 + with: + label: 'Potential Bugs' + status: ${{ steps.metrics.outputs.bugs }} + color: 'red' + path: badges/bugs.svg + - name: Commit updated badges + continue-on-error: true + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add badges/*.svg + git commit -m "Update badges with results from latest autograding" || true + - name: Push updated badges to GitHub repository + uses: ad-m/github-push-action@master + if: ${{ success() }} + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + branch: main +``` diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..a34f6fb --- /dev/null +++ b/action.yml @@ -0,0 +1,33 @@ +name: Quality Monitor +description: Action that monitors the quality of projects and pull requests. + +inputs: + config: + description: "Quality monitor configuration (if not set the default configuration will be used)" + required: false + checks-name: + description: "Name of the GitHub checks (if not set the default name will be used)" + required: false + pr-number: + description: "Pull request number (if not set, PR comments will be skipped)" + required: false + github-token: + description: "GitHub authentication token (GITHUB_TOKEN)" + required: true + skip-annotations: + description: "Skip the creation of annotations (for warnings and missed coverage) if not empty" + required: false + +runs: + using: 'docker' + image: 'docker://uhafner/quality-monitor:1.0.0-SNAPSHOT' + env: + CONFIG: ${{ inputs.config }} + CHECKS_NAME: ${{ inputs.checks-name }} + PR_NUMBER: ${{ inputs.pr-number }} + GITHUB_TOKEN: ${{ inputs.github-token }} + SKIP_ANNOTATIONS: ${{ inputs.skip-annotations }} + +branding: + icon: check-square + color: green diff --git a/doc/dependency-graph.puml b/doc/dependency-graph.puml new file mode 100644 index 0000000..df9bad7 --- /dev/null +++ b/doc/dependency-graph.puml @@ -0,0 +1,100 @@ +@startuml +skinparam defaultTextAlignment center +skinparam rectangle { + BackgroundColor<> beige + BackgroundColor<> lightGreen + BackgroundColor<> lightBlue + BackgroundColor<> lightGray +} +rectangle "jackson-databind\n\n2.16.0" as com_fasterxml_jackson_core_jackson_databind_jar +rectangle "jackson-annotations\n\n2.16.0" as com_fasterxml_jackson_core_jackson_annotations_jar +rectangle "jackson-core\n\n2.16.0" as com_fasterxml_jackson_core_jackson_core_jar +rectangle "autograding-model\n\n3.18.0" as edu_hm_hafner_autograding_model_jar +rectangle "autograding-github-action\n\n3.14.0-SNAPSHOT" as edu_hm_hafner_autograding_github_action_jar +rectangle "analysis-model\n\n11.13.0" as edu_hm_hafner_analysis_model_jar +rectangle "jsoup\n\n1.16.2" as org_jsoup_jsoup_jar +rectangle "commons-digester3\n\n3.2" as org_apache_commons_commons_digester3_jar +rectangle "cglib\n\n2.2.2" as cglib_cglib_jar +rectangle "commons-logging\n\n1.3.0" as commons_logging_commons_logging_jar +rectangle "commons-beanutils\n\n1.9.4" as commons_beanutils_commons_beanutils_jar +rectangle "commons-collections\n\n3.2.2" as commons_collections_commons_collections_jar +rectangle "commons-text\n\n1.10.0" as org_apache_commons_commons_text_jar +rectangle "violations-lib\n\n1.156.7" as se_bjurr_violations_violations_lib_jar +rectangle "j2html\n\n1.4.0" as com_j2html_j2html_jar +rectangle "xercesImpl\n\n2.12.2" as xerces_xercesImpl_jar +rectangle "xml-apis\n\n1.4.01" as xml_apis_xml_apis_jar +rectangle "asm\n\n9.6" as org_ow2_asm_asm_jar +rectangle "asm-analysis\n\n9.6" as org_ow2_asm_asm_analysis_jar +rectangle "asm-tree\n\n9.6" as org_ow2_asm_asm_tree_jar +rectangle "spotbugs\n\n4.8.0" as com_github_spotbugs_spotbugs_jar +rectangle "asm-commons\n\n9.6" as org_ow2_asm_asm_commons_jar +rectangle "asm-util\n\n9.6" as org_ow2_asm_asm_util_jar +rectangle "jcip-annotations\n\n1.0-1" as com_github_stephenc_jcip_jcip_annotations_jar +rectangle "dom4j\n\n2.1.4" as org_dom4j_dom4j_jar +rectangle "gson\n\n2.10.1" as com_google_code_gson_gson_jar +rectangle "bcel\n\n6.7.0" as org_apache_bcel_bcel_jar +rectangle "pmd-core\n\n6.55.0" as net_sourceforge_pmd_pmd_core_jar +rectangle "antlr4-runtime\n\n4.7.2" as org_antlr_antlr4_runtime_jar +rectangle "jcommander\n\n1.82" as com_beust_jcommander_jar +rectangle "pmd-java\n\n6.55.0" as net_sourceforge_pmd_pmd_java_jar +rectangle "json\n\n20231013" as org_json_json_jar +rectangle "json-smart\n\n2.5.0" as net_minidev_json_smart_jar +rectangle "accessors-smart\n\n2.5.0" as net_minidev_accessors_smart_jar +rectangle "slf4j-api\n\n2.0.9" as org_slf4j_slf4j_api_jar +rectangle "coverage-model\n\n0.36.0" as edu_hm_hafner_coverage_model_jar +rectangle "github-api\n\n1.318" as org_kohsuke_github_api_jar +rectangle "commons-io\n\n2.15.1" as commons_io_commons_io_jar +rectangle "commons-lang3\n\n3.14.0" as org_apache_commons_commons_lang3_jar +rectangle "spotbugs-annotations\n\n4.8.2" as com_github_spotbugs_spotbugs_annotations_jar +rectangle "error_prone_annotations\n\n2.23.0" as com_google_errorprone_error_prone_annotations_jar +rectangle "streamex\n\n0.8.2" as one_util_streamex_jar +rectangle "codingstyle\n\n3.30.0" as edu_hm_hafner_codingstyle_jar +com_fasterxml_jackson_core_jackson_databind_jar -[#000000]-> com_fasterxml_jackson_core_jackson_annotations_jar +com_fasterxml_jackson_core_jackson_databind_jar -[#000000]-> com_fasterxml_jackson_core_jackson_core_jar +edu_hm_hafner_autograding_model_jar -[#000000]-> com_fasterxml_jackson_core_jackson_databind_jar +edu_hm_hafner_autograding_github_action_jar -[#000000]-> edu_hm_hafner_autograding_model_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> org_jsoup_jsoup_jar +org_apache_commons_commons_digester3_jar -[#000000]-> cglib_cglib_jar +org_apache_commons_commons_digester3_jar -[#000000]-> commons_logging_commons_logging_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> org_apache_commons_commons_digester3_jar +commons_beanutils_commons_beanutils_jar .[#D3D3D3].> commons_logging_commons_logging_jar +commons_beanutils_commons_beanutils_jar -[#000000]-> commons_collections_commons_collections_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> commons_beanutils_commons_beanutils_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> org_apache_commons_commons_text_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> se_bjurr_violations_violations_lib_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> com_j2html_j2html_jar +xerces_xercesImpl_jar -[#000000]-> xml_apis_xml_apis_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> xerces_xercesImpl_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> org_ow2_asm_asm_jar +org_ow2_asm_asm_analysis_jar .[#D3D3D3].> org_ow2_asm_asm_tree_jar +com_github_spotbugs_spotbugs_jar -[#000000]-> org_ow2_asm_asm_analysis_jar +org_ow2_asm_asm_commons_jar .[#D3D3D3].> org_ow2_asm_asm_tree_jar +com_github_spotbugs_spotbugs_jar -[#000000]-> org_ow2_asm_asm_commons_jar +com_github_spotbugs_spotbugs_jar -[#000000]-> org_ow2_asm_asm_tree_jar +org_ow2_asm_asm_util_jar .[#D3D3D3].> org_ow2_asm_asm_tree_jar +org_ow2_asm_asm_util_jar .[#D3D3D3].> org_ow2_asm_asm_analysis_jar +com_github_spotbugs_spotbugs_jar -[#000000]-> org_ow2_asm_asm_util_jar +com_github_spotbugs_spotbugs_jar -[#000000]-> com_github_stephenc_jcip_jcip_annotations_jar +com_github_spotbugs_spotbugs_jar -[#000000]-> org_dom4j_dom4j_jar +com_github_spotbugs_spotbugs_jar -[#000000]-> com_google_code_gson_gson_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> com_github_spotbugs_spotbugs_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> org_apache_bcel_bcel_jar +net_sourceforge_pmd_pmd_core_jar -[#000000]-> org_antlr_antlr4_runtime_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> net_sourceforge_pmd_pmd_core_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> com_beust_jcommander_jar +net_sourceforge_pmd_pmd_java_jar .[#D3D3D3].> net_sourceforge_pmd_pmd_core_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> net_sourceforge_pmd_pmd_java_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> org_json_json_jar +net_minidev_json_smart_jar -[#000000]-> net_minidev_accessors_smart_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> net_minidev_json_smart_jar +edu_hm_hafner_analysis_model_jar -[#000000]-> org_slf4j_slf4j_api_jar +edu_hm_hafner_autograding_github_action_jar -[#000000]-> edu_hm_hafner_analysis_model_jar +edu_hm_hafner_autograding_github_action_jar -[#000000]-> edu_hm_hafner_coverage_model_jar +edu_hm_hafner_autograding_github_action_jar -[#000000]-> org_kohsuke_github_api_jar +edu_hm_hafner_autograding_github_action_jar -[#000000]-> commons_io_commons_io_jar +edu_hm_hafner_autograding_github_action_jar -[#000000]-> org_apache_commons_commons_lang3_jar +edu_hm_hafner_autograding_github_action_jar -[#000000]-> com_github_spotbugs_spotbugs_annotations_jar +edu_hm_hafner_autograding_github_action_jar -[#000000]-> com_google_errorprone_error_prone_annotations_jar +edu_hm_hafner_autograding_github_action_jar -[#000000]-> one_util_streamex_jar +edu_hm_hafner_autograding_github_action_jar -[#000000]-> edu_hm_hafner_codingstyle_jar +@enduml diff --git a/images/analysis-annotations.png b/images/analysis-annotations.png new file mode 100644 index 0000000..7550f56 Binary files /dev/null and b/images/analysis-annotations.png differ diff --git a/images/analysis.png b/images/analysis.png new file mode 100644 index 0000000..4879e47 Binary files /dev/null and b/images/analysis.png differ diff --git a/images/coverage-annotations.png b/images/coverage-annotations.png new file mode 100644 index 0000000..cb20f20 Binary files /dev/null and b/images/coverage-annotations.png differ diff --git a/images/coverage.png b/images/coverage.png new file mode 100644 index 0000000..c532e9c Binary files /dev/null and b/images/coverage.png differ diff --git a/images/details.png b/images/details.png new file mode 100644 index 0000000..a928278 Binary files /dev/null and b/images/details.png differ diff --git a/images/mutation-annotations.png b/images/mutation-annotations.png new file mode 100644 index 0000000..86149f8 Binary files /dev/null and b/images/mutation-annotations.png differ diff --git a/images/pr-comment.png b/images/pr-comment.png new file mode 100644 index 0000000..e28a279 Binary files /dev/null and b/images/pr-comment.png differ diff --git a/images/tests.png b/images/tests.png new file mode 100644 index 0000000..4aabf0b Binary files /dev/null and b/images/tests.png differ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..ab35368 --- /dev/null +++ b/pom.xml @@ -0,0 +1,125 @@ + + + 4.0.0 + + + edu.hm.hafner + codingstyle-pom + 3.40.0 + + + + edu.hm.hafner + quality-monitor + 1.0.0-SNAPSHOT + jar + + + ${project.groupId}.autograding.github.action + ${project.version} + + 17 + + 3.4.0 + 1.19.3 + + 2.16.0 + + + + + edu.hm.hafner + autograding-github-action + 3.14.0-SNAPSHOT + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-databind.version} + + + org.testcontainers + testcontainers + ${testcontainers.version} + test + + + org.testcontainers + junit-jupiter + ${testcontainers.version} + test + + + + + ${project.artifactId} + + + org.apache.maven.plugins + maven-failsafe-plugin + + @{argLine} --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED + + + + com.google.cloud.tools + jib-maven-plugin + ${jib-maven-plugin.version} + + + local-docker + pre-integration-test + + dockerBuild + + + + docker-io + install + + build + + + + docker.io/uhafner/quality-monitor:${docker-image-tag} + + ${env.DOCKER_IO_USERNAME} + ${env.DOCKER_IO_PASSWORD} + + + + + + + + docker.io/uhafner/quality-monitor:${docker-image-tag} + + ${env.DOCKER_IO_USERNAME} + ${env.DOCKER_IO_PASSWORD} + + + + maven:3.9.5-eclipse-temurin-21-alpine + + + + + org.revapi + revapi-maven-plugin + + true + + + + org.apache.maven.plugins + maven-javadoc-plugin + + true + + + + + + diff --git a/src/main/java/edu/hm/hafner/grading/github/QualityMonitor.java b/src/main/java/edu/hm/hafner/grading/github/QualityMonitor.java new file mode 100644 index 0000000..ddef28b --- /dev/null +++ b/src/main/java/edu/hm/hafner/grading/github/QualityMonitor.java @@ -0,0 +1,40 @@ +package edu.hm.hafner.grading.github; + +import java.io.PrintStream; + +import edu.hm.hafner.util.VisibleForTesting; + +/** + * GitHub action entrypoint for the autograding action. + * + * @author Tobias Effner + * @author Ullrich Hafner + */ +public class QualityMonitor extends GitHubAutoGradingRunner { + /** + * Public entry point for the GitHub action in the docker container, simply calls the action. + * + * @param unused + * not used + */ + public static void main(final String... unused) { + new QualityMonitor().run(); + } + + /** + * Creates a new instance of {@link QualityMonitor}. + */ + public QualityMonitor() { + super(); + } + + @VisibleForTesting + QualityMonitor(final PrintStream printStream) { + super(printStream); + } + + @Override + protected String getDefaultConfigurationPath() { + return "/default-no-score-config.json"; + } +} diff --git a/src/test/java/edu/hm/hafner/grading/github/QualityMonitorDockerITest.java b/src/test/java/edu/hm/hafner/grading/github/QualityMonitorDockerITest.java new file mode 100644 index 0000000..ee52650 --- /dev/null +++ b/src/test/java/edu/hm/hafner/grading/github/QualityMonitorDockerITest.java @@ -0,0 +1,226 @@ +package edu.hm.hafner.grading.github; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.ToStringConsumer; +import org.testcontainers.containers.output.WaitingConsumer; +import org.testcontainers.utility.DockerImageName; +import org.testcontainers.utility.MountableFile; + +import static org.assertj.core.api.Assertions.*; + +/** + * Integration test for the grading action. Starts the container and checks if the grading runs as expected. + * + * @author Ullrich Hafner + */ +public class QualityMonitorDockerITest { + private static final String CONFIGURATION = """ + { + "tests": { + "name": "JUnit", + "tools": [ + { + "id": "test", + "name": "Unittests", + "pattern": "**/target/*-reports/TEST*.xml" + } + ] + }, + "analysis": [ + { + "name": "Style", + "id": "style", + "tools": [ + { + "id": "checkstyle", + "name": "CheckStyle", + "pattern": "**/checkstyle*.xml" + }, + { + "id": "pmd", + "name": "PMD", + "pattern": "**/pmd*.xml" + } + ] + }, + { + "name": "Bugs", + "id": "bugs", + "tools": [ + { + "id": "spotbugs", + "name": "SpotBugs", + "pattern": "**/spotbugs*.xml" + } + ] + } + ], + "coverage": [ + { + "name": "JaCoCo", + "tools": [ + { + "id": "jacoco", + "name": "Line Coverage", + "metric": "line", + "pattern": "**/jacoco.xml" + }, + { + "id": "jacoco", + "name": "Branch Coverage", + "metric": "branch", + "pattern": "**/jacoco.xml" + } + ] + }, + { + "name": "PIT", + "tools": [ + { + "id": "pit", + "name": "Mutation Coverage", + "metric": "mutation", + "pattern": "**/mutations.xml" + } + ] + } + ] + } + """; + private static final String WS = "/github/workspace/target/"; + private static final String LOCAL_METRICS_FILE = "target/metrics.env"; + + @Test + void shouldGradeInDockerContainer() throws TimeoutException, IOException { + try (var container = createContainer()) { + container.withEnv("CONFIG", CONFIGURATION); + startContainerWithAllFiles(container); + + var metrics = new String[] { + "tests=1", + "line=11", + "branch=10", + "mutation=8", + "bugs=1", + "spotbugs=1", + "style=2", + "pmd=1", + "checkstyle=1"}; + + assertThat(readStandardOut(container)) + .contains("Obtaining configuration from environment variable CONFIG") + .contains(metrics) + .contains(new String[] { + "Processing 1 test configuration(s)", + "-> Unittests Total: TESTS: 1 tests", + "=> JUnit: 1 tests passed", + "Processing 2 coverage configuration(s)", + "-> Line Coverage Total: LINE: 10.93% (33/302)", + "-> Branch Coverage Total: BRANCH: 9.52% (4/42)", + "> JaCoCo: 10% coverage achieved", + "-> Mutation Coverage Total: MUTATION: 7.86% (11/140)", + "=> PIT: 8% mutations killed", + "Processing 2 static analysis configuration(s)", + "-> CheckStyle Total: 1 warnings", + "-> PMD Total: 1 warnings", + "=> Style: 2 warnings found (0 error, 0 high, 2 normal, 0 low)", + "-> SpotBugs Total: 1 warnings", + "=> Bugs: 1 warning found (0 error, 0 high, 0 normal, 1 low)"}); + + container.copyFileFromContainer("/github/workspace/metrics.env", LOCAL_METRICS_FILE); + assertThat(Files.readString(Path.of(LOCAL_METRICS_FILE))) + .contains(metrics); + } + } + + @Test + void shouldUseDefaultConfiguration() throws TimeoutException { + try (var container = createContainer()) { + startContainerWithAllFiles(container); + + assertThat(readStandardOut(container)) + .contains("No configuration provided (environment variable CONFIG not set), using default configuration") + .contains(new String[] { + "Processing 1 test configuration(s)", + "-> Tests Total: TESTS: 1 tests", + "=> Tests: 1 tests passed", + "Processing 2 coverage configuration(s)", + "-> Line Coverage Total: LINE: 10.93% (33/302)", + "-> Branch Coverage Total: BRANCH: 9.52% (4/42)", + "=> Code Coverage: 10% coverage achieved", + "-> Mutation Coverage Total: MUTATION: 7.86% (11/140)", + "=> Mutation Coverage: 8% mutations killed", + "Processing 2 static analysis configuration(s)", + "-> CheckStyle Total: 1 warnings", + "-> PMD Total: 1 warnings", + "=> Style: 2 warnings found (0 error, 0 high, 2 normal, 0 low)", + "-> SpotBugs Total: 1 warnings", + "=> Bugs: 1 warning found (0 error, 0 high, 0 normal, 1 low)"}); + } + } + + @Test + void shouldShowErrors() throws TimeoutException { + try (var container = createContainer()) { + container.withWorkingDirectory("/github/workspace").start(); + assertThat(readStandardOut(container)) + .contains(new String[] { + "Processing 1 test configuration(s)", + "-> Tests Total: TESTS: 0 tests", + "Configuration error for 'Tests'?", + "=> Tests: 0 tests passed", + "Processing 2 coverage configuration(s)", + "=> Code Coverage: 0% coverage achieved", + "Configuration error for 'Line Coverage'?", + "Configuration error for 'Branch Coverage'?", + "=> Mutation Coverage: 0% mutations killed", + "Configuration error for 'Mutation Coverage'?", + "Processing 2 static analysis configuration(s)", + "Configuration error for 'CheckStyle'?", + "Configuration error for 'PMD'?", + "Configuration error for 'SpotBugs'?", + "-> CheckStyle Total: 0 warnings", + "-> PMD Total: 0 warnings", + "=> Style: No warnings found", + "-> SpotBugs Total: 0 warnings", + "=> Bugs: No warnings found"}); + } + } + + private GenericContainer createContainer() { + return new GenericContainer<>(DockerImageName.parse("uhafner/quality-monitor:1.0.0-SNAPSHOT")); + } + + private String readStandardOut(final GenericContainer> container) throws TimeoutException { + var waitingConsumer = new WaitingConsumer(); + var toStringConsumer = new ToStringConsumer(); + + var composedConsumer = toStringConsumer.andThen(waitingConsumer); + container.followOutput(composedConsumer); + waitingConsumer.waitUntil(frame -> frame.getUtf8String().contains("End Grading"), 60, TimeUnit.SECONDS); + + return toStringConsumer.toUtf8String(); + } + + private void startContainerWithAllFiles(final GenericContainer container) { + container.withWorkingDirectory("/github/workspace") + .withCopyFileToContainer(read("checkstyle/checkstyle-result.xml"), WS + "checkstyle-result.xml") + .withCopyFileToContainer(read("jacoco/jacoco.xml"), WS + "site/jacoco/jacoco.xml") + .withCopyFileToContainer(read("junit/TEST-edu.hm.hafner.grading.AutoGradingActionTest.xml"), WS + "surefire-reports/TEST-Aufgabe3Test.xml") + .withCopyFileToContainer(read("pit/mutations.xml"), WS + "pit-reports/mutations.xml") + .withCopyFileToContainer(read("pmd/pmd.xml"), WS + "pmd.xml") + .withCopyFileToContainer(read("spotbugs/spotbugsXml.xml"), WS + "spotbugsXml.xml") + .start(); + } + + private MountableFile read(final String resourceName) { + return MountableFile.forClasspathResource("/" + resourceName); + } +} diff --git a/src/test/java/edu/hm/hafner/grading/github/QualityMonitorITest.java b/src/test/java/edu/hm/hafner/grading/github/QualityMonitorITest.java new file mode 100644 index 0000000..0c2b6d7 --- /dev/null +++ b/src/test/java/edu/hm/hafner/grading/github/QualityMonitorITest.java @@ -0,0 +1,278 @@ +package edu.hm.hafner.grading.github; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; + +import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.SetEnvironmentVariable; + +import edu.hm.hafner.util.ResourceTest; + +import static org.assertj.core.api.Assertions.*; + +/** + * Integration test for the grading action. Runs the action locally in the filesystem. + * + * @author Ullrich Hafner + */ +public class QualityMonitorITest extends ResourceTest { + private static final String CONFIGURATION = """ + { + "tests": { + "name": "JUnit", + "tools": [ + { + "id": "test", + "name": "Unittests", + "pattern": "**/src/**/TEST*.xml" + } + ] + }, + "analysis": [ + { + "name": "Style", + "id": "style", + "tools": [ + { + "id": "checkstyle", + "name": "CheckStyle", + "pattern": "**/src/**/checkstyle*.xml" + }, + { + "id": "pmd", + "name": "PMD", + "pattern": "**/src/**/pmd*.xml" + } + ] + }, + { + "name": "Bugs", + "id": "bugs", + "tools": [ + { + "id": "spotbugs", + "name": "SpotBugs", + "pattern": "**/src/**/spotbugs*.xml" + } + ] + } + ], + "coverage": [ + { + "name": "JaCoCo", + "tools": [ + { + "id": "jacoco", + "name": "Line Coverage", + "metric": "line", + "pattern": "**/src/**/jacoco.xml" + }, + { + "id": "jacoco", + "name": "Branch Coverage", + "metric": "branch", + "pattern": "**/src/**/jacoco.xml" + } + ] + }, + { + "name": "PIT", + "tools": [ + { + "id": "pit", + "name": "Mutation Coverage", + "metric": "mutation", + "pattern": "**/src/**/mutations.xml" + } + ] + } + ] + } + """; + + @Test + void shouldMonitorQualityWithDefaultConfiguration() { + assertThat(runAutoGrading()) + .contains( + "No configuration provided (environment variable CONFIG not set), using default configuration") + .contains(new String[] { + "Processing 1 test configuration(s)", + "\"maxScore\" : 0,", + "\"failureImpact\" : 0,", + "\"passedImpact\" : 0,", + "\"skippedImpact\" : 0", + "=> Tests: 1 tests passed", + "Processing 2 coverage configuration(s)", + "\"coveredPercentageImpact\" : 0,", + "\"missedPercentageImpact\" : 0,", + "=> Code Coverage: 0% coverage achieved", + "=> Mutation Coverage: 0% mutations killed", + "Processing 2 static analysis configuration(s)", + "\"errorImpact\" : 0,", + "\"highImpact\" : 0,", + "\"lowImpact\" : 0", + "\"normalImpact\" : 0,", + "=> Style: No warnings found", + "=> Bugs: No warnings found"}); + } + + @Test + @SetEnvironmentVariable(key = "CONFIG", value = CONFIGURATION) + void shouldGradeWithConfigurationFromEnvironment() { + assertThat(runAutoGrading()) + .contains("Obtaining configuration from environment variable CONFIG") + .contains(new String[] { + "Processing 1 test configuration(s)", + "=> JUnit: 13 tests failed, 24 passed", + "Processing 2 coverage configuration(s)", + "-> Line Coverage Total: LINE: 10.93% (33/302)", + "-> Branch Coverage Total: BRANCH: 9.52% (4/42)", + "=> JaCoCo: 10% coverage achieved", + "-> Mutation Coverage Total: MUTATION: 7.86% (11/140)", + "=> PIT: 8% mutations killed", + "Processing 2 static analysis configuration(s)", + "-> CheckStyle Total: 19 warnings", + "-> PMD Total: 41 warnings", + "=> Style: 60 warnings found (0 error, 0 high, 60 normal, 0 low)", + "-> SpotBugs Total: 1 warnings", + "=> Bugs: 1 warning found (0 error, 0 high, 0 normal, 1 low)", + "mutation=8", + "bugs=1", + "tests=37", + "line=11", + "pmd=41", + "style=60", + "spotbugs=1", + "checkstyle=19", + "branch=10"}); + } + + private static final String CONFIGURATION_WRONG_PATHS = """ + { + "tests": { + "tools": [ + { + "id": "test", + "name": "Unittests", + "pattern": "**/does-not-exist/TEST*.xml" + } + ], + "name": "JUnit", + "passedImpact": 10, + "skippedImpact": -1, + "failureImpact": -5, + "maxScore": 100 + }, + "analysis": [ + { + "name": "Style", + "id": "style", + "tools": [ + { + "id": "checkstyle", + "name": "CheckStyle", + "pattern": "**/does-not-exist/checkstyle*.xml" + }, + { + "id": "pmd", + "name": "PMD", + "pattern": "**/does-not-exist/pmd*.xml" + } + ], + "errorImpact": 1, + "highImpact": 2, + "normalImpact": 3, + "lowImpact": 4, + "maxScore": 100 + }, + { + "name": "Bugs", + "id": "bugs", + "tools": [ + { + "id": "spotbugs", + "name": "SpotBugs", + "pattern": "**/does-not-exist/spotbugs*.xml" + } + ], + "errorImpact": -11, + "highImpact": -12, + "normalImpact": -13, + "lowImpact": -14, + "maxScore": 100 + } + ], + "coverage": [ + { + "tools": [ + { + "id": "jacoco", + "name": "Line Coverage", + "metric": "line", + "pattern": "**/does-not-exist/jacoco.xml" + }, + { + "id": "jacoco", + "name": "Branch Coverage", + "metric": "branch", + "pattern": "**/does-not-exist/jacoco.xml" + } + ], + "name": "JaCoCo", + "maxScore": 100, + "coveredPercentageImpact": 1, + "missedPercentageImpact": -1 + }, + { + "tools": [ + { + "id": "pit", + "name": "Mutation Coverage", + "metric": "mutation", + "pattern": "**/does-not-exist/mutations.xml" + } + ], + "name": "PIT", + "maxScore": 100, + "coveredPercentageImpact": 1, + "missedPercentageImpact": -1 + } + ] + } + """; + + @Test + @SetEnvironmentVariable(key = "CONFIG", value = CONFIGURATION_WRONG_PATHS) + void shouldShowErrors() { + assertThat(runAutoGrading()) + .contains(new String[] { + "Processing 1 test configuration(s)", + "-> Unittests Total: TESTS: 0 tests", + "Configuration error for 'Unittests'?", + "JUnit Score: 100 of 100", + "Processing 2 coverage configuration(s)", + "=> JaCoCo Score: 0 of 100", + "Configuration error for 'Line Coverage'?", + "Configuration error for 'Branch Coverage'?", + "=> PIT Score: 0 of 100", + "Configuration error for 'Mutation Coverage'?", + "Processing 2 static analysis configuration(s)", + "Configuration error for 'CheckStyle'?", + "Configuration error for 'PMD'?", + "Configuration error for 'SpotBugs'?", + "-> CheckStyle Total: 0 warnings", + "-> PMD Total: 0 warnings", + "=> Style Score: 0 of 100", + "-> SpotBugs Total: 0 warnings", + "=> Bugs Score: 100 of 100", + "Autograding score - 200 of 500"}); + } + + private String runAutoGrading() { + var outputStream = new ByteArrayOutputStream(); + var runner = new QualityMonitor(new PrintStream(outputStream)); + runner.run(); + return outputStream.toString(StandardCharsets.UTF_8); + } +} diff --git a/src/test/java/edu/hm/hafner/grading/github/QualityMonitorTest.java b/src/test/java/edu/hm/hafner/grading/github/QualityMonitorTest.java new file mode 100644 index 0000000..279ad2f --- /dev/null +++ b/src/test/java/edu/hm/hafner/grading/github/QualityMonitorTest.java @@ -0,0 +1,14 @@ +package edu.hm.hafner.grading.github; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + +class QualityMonitorTest { + @Test + void shouldCreateInstance() { + var qualityMonitor = new QualityMonitor(); + + assertThat(qualityMonitor.getDefaultConfigurationPath()).isEqualTo("/default-no-score-config.json"); + } +} diff --git a/src/test/resources/checkstyle/checkstyle-ignores.xml b/src/test/resources/checkstyle/checkstyle-ignores.xml new file mode 100644 index 0000000..2c73f16 --- /dev/null +++ b/src/test/resources/checkstyle/checkstyle-ignores.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/checkstyle/checkstyle-result.xml b/src/test/resources/checkstyle/checkstyle-result.xml new file mode 100644 index 0000000..74c5133 --- /dev/null +++ b/src/test/resources/checkstyle/checkstyle-result.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/jacoco/jacoco.xml b/src/test/resources/jacoco/jacoco.xml new file mode 100644 index 0000000..d27dce0 --- /dev/null +++ b/src/test/resources/jacoco/jacoco.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/test/resources/junit/TEST-Aufgabe3Test.xml b/src/test/resources/junit/TEST-Aufgabe3Test.xml new file mode 100644 index 0000000..a184971 --- /dev/null +++ b/src/test/resources/junit/TEST-Aufgabe3Test.xml @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +to be equal to: + <[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], []]]]> +when comparing elements using recursive field/property by field/property comparator on all fields/properties +Comparators used: +- for elements fields (by type): {Double -> DoubleComparator[precision=1.0E-15], Float -> FloatComparator[precision=1.0E-6]} +- for elements (by type): {Double -> DoubleComparator[precision=1.0E-15], Float -> FloatComparator[precision=1.0E-6]} +but was not. + at Aufgabe3Test.shouldSplitToEmptyRight(Aufgabe3Test.java:254) +]]> + + + +to be equal to: + <[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], []]]]> +when comparing elements using recursive field/property by field/property comparator on all fields/properties +Comparators used: +- for elements fields (by type): {Double -> DoubleComparator[precision=1.0E-15], Float -> FloatComparator[precision=1.0E-6]} +- for elements (by type): {Double -> DoubleComparator[precision=1.0E-15], Float -> FloatComparator[precision=1.0E-6]} +but was not. + at Aufgabe3Test.shouldSplitToEmptyRight(Aufgabe3Test.java:254) +]]> + + + +to be equal to: + <[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], []]]]> +when comparing elements using recursive field/property by field/property comparator on all fields/properties +Comparators used: +- for elements fields (by type): {Double -> DoubleComparator[precision=1.0E-15], Float -> FloatComparator[precision=1.0E-6]} +- for elements (by type): {Double -> DoubleComparator[precision=1.0E-15], Float -> FloatComparator[precision=1.0E-6]} +but was not. + at Aufgabe3Test.shouldSplitToEmptyRight(Aufgabe3Test.java:254) +]]> + + + + + + + + + +to be equal to: + <[[], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]]]> +when comparing elements using recursive field/property by field/property comparator on all fields/properties +Comparators used: +- for elements fields (by type): {Double -> DoubleComparator[precision=1.0E-15], Float -> FloatComparator[precision=1.0E-6]} +- for elements (by type): {Double -> DoubleComparator[precision=1.0E-15], Float -> FloatComparator[precision=1.0E-6]} +but was not. + at Aufgabe3Test.shouldSplit(Aufgabe3Test.java:219) +]]> + + + + + + + + + + + + + + + + +to contain exactly (and in same order): + <[1]> +but some elements were not found: + <[1]> +and others were not expected: + <[0, 0]> + + at Aufgabe3Test.shouldRemoveDuplicates(Aufgabe3Test.java:299) +]]> + + + + +to be equal to: + <[10, 1]> +when recursively comparing field by field, but found the following 2 differences: + +field/property 'value' differ: +- actual value : 10 +- expected value : 1 + +field/property 'value' differ: +- actual value : 1 +- expected value : 10 + +The recursive comparison was performed with this configuration: +- no overridden equals methods were used in the comparison (except for java types) +- these types were compared with the following comparators: + - java.lang.Double -> DoubleComparator[precision=1.0E-15] + - java.lang.Float -> FloatComparator[precision=1.0E-6] +- actual and expected objects and their fields were compared field by field recursively even if they were not of the same type, this allows for example to compare a Person to a PersonDto (call strictTypeChecking(true) to change that behavior). + + at Aufgabe3Test.shouldInsertBeforeAdditional(Aufgabe3Test.java:152) +]]> + + + + + + +to be equal to: + <[[], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]]]> +when comparing elements using recursive field/property by field/property comparator on all fields/properties +Comparators used: +- for elements fields (by type): {Double -> DoubleComparator[precision=1.0E-15], Float -> FloatComparator[precision=1.0E-6]} +- for elements (by type): {Double -> DoubleComparator[precision=1.0E-15], Float -> FloatComparator[precision=1.0E-6]} +but was not. + at Aufgabe3Test.shouldSplitToEmptyLeft(Aufgabe3Test.java:242) +]]> + + + +to be equal to: + <[[], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]]]> +when comparing elements using recursive field/property by field/property comparator on all fields/properties +Comparators used: +- for elements fields (by type): {Double -> DoubleComparator[precision=1.0E-15], Float -> FloatComparator[precision=1.0E-6]} +- for elements (by type): {Double -> DoubleComparator[precision=1.0E-15], Float -> FloatComparator[precision=1.0E-6]} +but was not. + at Aufgabe3Test.shouldSplitToEmptyLeft(Aufgabe3Test.java:242) +]]> + + + +to be equal to: + <[[], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]]]> +when comparing elements using recursive field/property by field/property comparator on all fields/properties +Comparators used: +- for elements fields (by type): {Double -> DoubleComparator[precision=1.0E-15], Float -> FloatComparator[precision=1.0E-6]} +- for elements (by type): {Double -> DoubleComparator[precision=1.0E-15], Float -> FloatComparator[precision=1.0E-6]} +but was not. + at Aufgabe3Test.shouldSplitToEmptyLeft(Aufgabe3Test.java:242) +]]> + + + +to contain exactly (and in same order): + <[1, 2, 3]> +but some elements were not found: + <[1, 2, 3]> +and others were not expected: + <[-1, -1, -1]> + + at Aufgabe3Test.shouldCopyValues(Aufgabe3Test.java:63) +]]> + + + + is not final in (Integers.java:0) +]]> + + \ No newline at end of file diff --git a/src/test/resources/junit/TEST-edu.hm.hafner.grading.AutoGradingActionTest.xml b/src/test/resources/junit/TEST-edu.hm.hafner.grading.AutoGradingActionTest.xml new file mode 100644 index 0000000..46ae2b0 --- /dev/null +++ b/src/test/resources/junit/TEST-edu.hm.hafner.grading.AutoGradingActionTest.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/junit/TEST-edu.hm.hafner.grading.ReportFinderTest.xml b/src/test/resources/junit/TEST-edu.hm.hafner.grading.ReportFinderTest.xml new file mode 100644 index 0000000..bc90fd0 --- /dev/null +++ b/src/test/resources/junit/TEST-edu.hm.hafner.grading.ReportFinderTest.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/pit/mutations.xml b/src/test/resources/pit/mutations.xml new file mode 100644 index 0000000..f587e45 --- /dev/null +++ b/src/test/resources/pit/mutations.xml @@ -0,0 +1,2438 @@ + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + addCheckLink + (Lorg/kohsuke/github/GHCheckRun;)Ljava/lang/String; + 120 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 17 + + + 3 + + + replaced return value with "" for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::addCheckLink + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + addComment + + (Ljava/lang/String;Ledu/hm/hafner/grading/AggregatedScore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ledu/hm/hafner/grading/github/GitHubPullRequestWriter$ChecksStatus;)V + + 70 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 11 + + + 2 + + + negated conditional + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + addComment + + (Ljava/lang/String;Ledu/hm/hafner/grading/AggregatedScore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ledu/hm/hafner/grading/github/GitHubPullRequestWriter$ChecksStatus;)V + + 76 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 31 + + + 7 + + + negated conditional + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + addComment + + (Ljava/lang/String;Ledu/hm/hafner/grading/AggregatedScore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ledu/hm/hafner/grading/github/GitHubPullRequestWriter$ChecksStatus;)V + + 93 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 96 + + + 24 + + + negated conditional + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + addComment + + (Ljava/lang/String;Ledu/hm/hafner/grading/AggregatedScore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ledu/hm/hafner/grading/github/GitHubPullRequestWriter$ChecksStatus;)V + + 107 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 164 + + + 39 + + + negated conditional + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + addComment + + (Ljava/lang/String;Ledu/hm/hafner/grading/AggregatedScore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ledu/hm/hafner/grading/github/GitHubPullRequestWriter$ChecksStatus;)V + + 71 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 16 + + + 3 + + + removed call to java/io/PrintStream::println + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + addComment + + (Ljava/lang/String;Ledu/hm/hafner/grading/AggregatedScore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ledu/hm/hafner/grading/github/GitHubPullRequestWriter$ChecksStatus;)V + + 77 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 36 + + + 8 + + + removed call to java/io/PrintStream::println + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + addComment + + (Ljava/lang/String;Ledu/hm/hafner/grading/AggregatedScore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ledu/hm/hafner/grading/github/GitHubPullRequestWriter$ChecksStatus;)V + + 83 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 57 + + + 13 + + + removed call to java/io/PrintStream::println + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + addComment + + (Ljava/lang/String;Ledu/hm/hafner/grading/AggregatedScore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ledu/hm/hafner/grading/github/GitHubPullRequestWriter$ChecksStatus;)V + + 99 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 135 + + + 32 + + + removed call to edu/hm/hafner/grading/github/GitHubPullRequestWriter::handleAnnotations + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + addComment + + (Ljava/lang/String;Ledu/hm/hafner/grading/AggregatedScore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ledu/hm/hafner/grading/github/GitHubPullRequestWriter$ChecksStatus;)V + + 104 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 153 + + + 36 + + + removed call to java/io/PrintStream::println + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + addComment + + (Ljava/lang/String;Ledu/hm/hafner/grading/AggregatedScore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ledu/hm/hafner/grading/github/GitHubPullRequestWriter$ChecksStatus;)V + + 111 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 189 + + + 45 + + + removed call to java/io/PrintStream::println + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + addComment + + (Ljava/lang/String;Ledu/hm/hafner/grading/AggregatedScore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ledu/hm/hafner/grading/github/GitHubPullRequestWriter$ChecksStatus;)V + + 115 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 204 + + + 48 + + + removed call to java/io/PrintStream::println + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createAnnotation + + (Ljava/util/regex/Pattern;Ledu/hm/hafner/analysis/Issue;)Lorg/kohsuke/github/GHCheckRunBuilder$Annotation; + + 152 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 33 + + + 11 + + + negated conditional + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createAnnotation + + (Ljava/util/regex/Pattern;Ledu/hm/hafner/analysis/Issue;)Lorg/kohsuke/github/GHCheckRunBuilder$Annotation; + + 153 + org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator + + 45 + + + 18 + + + replaced return value with null for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::createAnnotation + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createAnnotation + + (Ljava/util/regex/Pattern;Ledu/hm/hafner/analysis/Issue;)Lorg/kohsuke/github/GHCheckRunBuilder$Annotation; + + 155 + org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator + + 50 + + + 19 + + + replaced return value with null for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::createAnnotation + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createBranchCoverageAnnotation + (Ljava/util/regex/Pattern;Ledu/hm/hafner/coverage/FileNode;)Ljava/util/List; + 205 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 21 + + + 6 + + + replaced return value with Collections.emptyList for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::createBranchCoverageAnnotation + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createBranchMessage + (II)Ljava/lang/String; + 215 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 5 + + + 0 + + + negated conditional + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createBranchMessage + (II)Ljava/lang/String; + 216 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 17 + + + 3 + + + replaced return value with "" for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::createBranchMessage + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createBranchMessage + (II)Ljava/lang/String; + 219 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 35 + + + 7 + + + replaced return value with "" for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::createBranchMessage + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createLineAnnotationsForMissedLines + + (Ledu/hm/hafner/grading/AggregatedScore;Ljava/util/regex/Pattern;Lorg/kohsuke/github/GHCheckRunBuilder$Output;)V + + 166 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 35 + + + 8 + + + removed call to java/util/stream/Stream::forEach + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createLineAnnotationsForPartiallyCoveredLines + + (Ledu/hm/hafner/grading/AggregatedScore;Ljava/util/regex/Pattern;Lorg/kohsuke/github/GHCheckRunBuilder$Output;)V + + 201 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 35 + + + 8 + + + removed call to java/util/stream/Stream::forEach + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createLineAnnotationsForSurvivedMutations + + (Ledu/hm/hafner/grading/AggregatedScore;Ljava/util/regex/Pattern;Lorg/kohsuke/github/GHCheckRunBuilder$Output;)V + + 230 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 35 + + + 8 + + + removed call to java/util/stream/Stream::forEach + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createLineAnnotationsForWarnings + + (Ledu/hm/hafner/grading/AggregatedScore;Ljava/util/regex/Pattern;Lorg/kohsuke/github/GHCheckRunBuilder$Output;)V + + 145 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 27 + + + 6 + + + removed call to java/util/stream/Stream::forEach + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createLineCoverageAnnotation + (Ljava/util/regex/Pattern;Ledu/hm/hafner/coverage/FileNode;)Ljava/util/List; + 170 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 20 + + + 5 + + + replaced return value with Collections.emptyList for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::createLineCoverageAnnotation + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createMutationCoverageAnnotation + (Ljava/util/regex/Pattern;Ledu/hm/hafner/coverage/FileNode;)Ljava/util/List; + 234 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 21 + + + 6 + + + replaced return value with Collections.emptyList for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::createMutationCoverageAnnotation + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createMutationDetails + (Ljava/util/List;)Ljava/lang/String; + 256 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 19 + + + 4 + + + replaced return value with "" for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::createMutationDetails + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createMutationMessage + (ILjava/util/List;)Ljava/lang/String; + 245 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 6 + + + 1 + + + negated conditional + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createMutationMessage + (ILjava/util/List;)Ljava/lang/String; + 246 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 24 + + + 5 + + + replaced return value with "" for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::createMutationMessage + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + createMutationMessage + (ILjava/util/List;)Ljava/lang/String; + 248 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 43 + + + 10 + + + replaced return value with "" for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::createMutationMessage + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + formatMutator + (Ljava/util/List;)Ljava/lang/String; + 252 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 11 + + + 3 + + + replaced return value with "" for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::formatMutator + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + getEnv + (Ljava/lang/String;)Ljava/lang/String; + 126 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 13 + + + 2 + + + removed call to java/io/PrintStream::println + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + getEnv + (Ljava/lang/String;)Ljava/lang/String; + 127 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 17 + + + 3 + + + replaced return value with "" for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::getEnv + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + getMissedLinesDescription + (Ledu/hm/hafner/util/LineRange;)Ljava/lang/String; + 187 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 7 + + + 2 + + + negated conditional + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + getMissedLinesDescription + (Ledu/hm/hafner/util/LineRange;)Ljava/lang/String; + 188 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 20 + + + 6 + + + replaced return value with "" for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::getMissedLinesDescription + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + getMissedLinesDescription + (Ledu/hm/hafner/util/LineRange;)Ljava/lang/String; + 190 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 40 + + + 12 + + + replaced return value with "" for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::getMissedLinesDescription + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + getMissedLinesMessage + (Ledu/hm/hafner/util/LineRange;)Ljava/lang/String; + 180 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 7 + + + 2 + + + negated conditional + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + getMissedLinesMessage + (Ledu/hm/hafner/util/LineRange;)Ljava/lang/String; + 181 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 11 + + + 3 + + + replaced return value with "" for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::getMissedLinesMessage + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + getMissedLinesMessage + (Ledu/hm/hafner/util/LineRange;)Ljava/lang/String; + 183 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 16 + + + 4 + + + replaced return value with "" for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::getMissedLinesMessage + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + handleAnnotations + + (Ledu/hm/hafner/grading/AggregatedScore;Ljava/util/regex/Pattern;Lorg/kohsuke/github/GHCheckRunBuilder$Output;)V + + 131 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 7 + + + 2 + + + negated conditional + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + handleAnnotations + + (Ledu/hm/hafner/grading/AggregatedScore;Ljava/util/regex/Pattern;Lorg/kohsuke/github/GHCheckRunBuilder$Output;)V + + 132 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 14 + + + 3 + + + removed call to + edu/hm/hafner/grading/github/GitHubPullRequestWriter::createLineAnnotationsForWarnings + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + handleAnnotations + + (Ledu/hm/hafner/grading/AggregatedScore;Ljava/util/regex/Pattern;Lorg/kohsuke/github/GHCheckRunBuilder$Output;)V + + 133 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 21 + + + 4 + + + removed call to + edu/hm/hafner/grading/github/GitHubPullRequestWriter::createLineAnnotationsForMissedLines + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + handleAnnotations + + (Ledu/hm/hafner/grading/AggregatedScore;Ljava/util/regex/Pattern;Lorg/kohsuke/github/GHCheckRunBuilder$Output;)V + + 134 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 28 + + + 5 + + + removed call to + edu/hm/hafner/grading/github/GitHubPullRequestWriter::createLineAnnotationsForPartiallyCoveredLines + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + handleAnnotations + + (Ledu/hm/hafner/grading/AggregatedScore;Ljava/util/regex/Pattern;Lorg/kohsuke/github/GHCheckRunBuilder$Output;)V + + 135 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 35 + + + 6 + + + removed call to + edu/hm/hafner/grading/github/GitHubPullRequestWriter::createLineAnnotationsForSurvivedMutations + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + lambda$createBranchCoverageAnnotation$4 + + (Ljava/util/regex/Pattern;Ledu/hm/hafner/coverage/FileNode;Ljava/util/Map$Entry;)Lorg/kohsuke/github/GHCheckRunBuilder$Annotation; + + 206 + org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator + + 37 + + + 12 + + + replaced return value with null for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::lambda$createBranchCoverageAnnotation$4 + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + lambda$createLineAnnotationsForMissedLines$1 + (Ljava/util/regex/Pattern;Ledu/hm/hafner/coverage/FileNode;)Ljava/util/List; + 164 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 7 + + + 1 + + + replaced return value with Collections.emptyList for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::lambda$createLineAnnotationsForMissedLines$1 + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + lambda$createLineAnnotationsForPartiallyCoveredLines$3 + (Ljava/util/regex/Pattern;Ledu/hm/hafner/coverage/FileNode;)Ljava/util/List; + 199 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 7 + + + 1 + + + replaced return value with Collections.emptyList for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::lambda$createLineAnnotationsForPartiallyCoveredLines$3 + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + lambda$createLineAnnotationsForSurvivedMutations$5 + (Ljava/util/regex/Pattern;Ledu/hm/hafner/coverage/FileNode;)Ljava/util/List; + 228 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 7 + + + 1 + + + replaced return value with Collections.emptyList for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::lambda$createLineAnnotationsForSurvivedMutations$5 + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + lambda$createLineAnnotationsForWarnings$0 + + (Ljava/util/regex/Pattern;Ledu/hm/hafner/analysis/Issue;)Lorg/kohsuke/github/GHCheckRunBuilder$Annotation; + + 144 + org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator + + 7 + + + 1 + + + replaced return value with null for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::lambda$createLineAnnotationsForWarnings$0 + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + lambda$createLineCoverageAnnotation$2 + + (Ljava/util/regex/Pattern;Ledu/hm/hafner/coverage/FileNode;Ledu/hm/hafner/util/LineRange;)Lorg/kohsuke/github/GHCheckRunBuilder$Annotation; + + 171 + org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator + + 32 + + + 9 + + + replaced return value with null for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::lambda$createLineCoverageAnnotation$2 + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + lambda$createMutationCoverageAnnotation$6 + + (Ljava/util/regex/Pattern;Ledu/hm/hafner/coverage/FileNode;Ljava/util/Map$Entry;)Lorg/kohsuke/github/GHCheckRunBuilder$Annotation; + + 235 + org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator + + 44 + + + 14 + + + replaced return value with null for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::lambda$createMutationCoverageAnnotation$6 + + + + GitHubPullRequestWriter.java + edu.hm.hafner.grading.github.GitHubPullRequestWriter + lambda$createMutationDetails$7 + (Ledu/hm/hafner/coverage/Mutation;)Ljava/lang/String; + 257 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 17 + + + 3 + + + replaced return value with "" for + edu/hm/hafner/grading/github/GitHubPullRequestWriter::lambda$createMutationDetails$7 + + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + createEnvironmentVariables + (Ledu/hm/hafner/grading/AggregatedScore;)Ljava/lang/String; + 131 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 13 + + + 2 + + + removed call to java/util/Map::forEach + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + createEnvironmentVariables + (Ledu/hm/hafner/grading/AggregatedScore;)Ljava/lang/String; + 132 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 18 + + + 3 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + createEnvironmentVariables + (Ledu/hm/hafner/grading/AggregatedScore;)Ljava/lang/String; + 133 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 23 + + + 4 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + createEnvironmentVariables + (Ledu/hm/hafner/grading/AggregatedScore;)Ljava/lang/String; + 134 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 28 + + + 5 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + createEnvironmentVariables + (Ledu/hm/hafner/grading/AggregatedScore;)Ljava/lang/String; + 135 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 33 + + + 6 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + createEnvironmentVariables + (Ledu/hm/hafner/grading/AggregatedScore;)Ljava/lang/String; + 136 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 38 + + + 8 + + + replaced return value with "" for + edu/hm/hafner/grading/AutoGradingAction::createEnvironmentVariables + + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + getChecksName + ()Ljava/lang/String; + 140 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 8 + + + 2 + + + replaced return value with "" for edu/hm/hafner/grading/AutoGradingAction::getChecksName + + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + getConfiguration + ()Ljava/lang/String; + 146 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 10 + + + 2 + + + edu.hm.hafner.grading.AutoGradingRunnerTest.[engine:junit-jupiter]/[class:edu.hm.hafner.grading.AutoGradingRunnerTest]/[method:shouldReadDefaultConfigurationIfEnvironmentIsNotSet()] + + negated conditional + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + getConfiguration + ()Ljava/lang/String; + 147 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 15 + + + 3 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + getConfiguration + ()Ljava/lang/String; + 152 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 26 + + + 6 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + getConfiguration + ()Ljava/lang/String; + 149 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 20 + + + 5 + + + edu.hm.hafner.grading.AutoGradingRunnerTest.[engine:junit-jupiter]/[class:edu.hm.hafner.grading.AutoGradingRunnerTest]/[method:shouldReadDefaultConfigurationIfEnvironmentIsNotSet()] + + replaced return value with "" for edu/hm/hafner/grading/AutoGradingAction::getConfiguration + + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + getConfiguration + ()Ljava/lang/String; + 153 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 30 + + + 7 + + + replaced return value with "" for edu/hm/hafner/grading/AutoGradingAction::getConfiguration + + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + lambda$run$0 + (Ljava/lang/String;)Ljava/nio/file/Path; + 80 + org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator + + 7 + + + 1 + + + replaced return value with null for edu/hm/hafner/grading/AutoGradingAction::lambda$run$0 + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + lambda$run$1 + (Ljava/nio/file/Path;)Z + 81 + org.pitest.mutationtest.engine.gregor.mutators.returns.BooleanFalseReturnValsMutator + + 7 + + + 1 + + + replaced boolean return with false for edu/hm/hafner/grading/AutoGradingAction::lambda$run$1 + + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + lambda$run$1 + (Ljava/nio/file/Path;)Z + 81 + org.pitest.mutationtest.engine.gregor.mutators.returns.BooleanTrueReturnValsMutator + + 7 + + + 1 + + + replaced boolean return with true for edu/hm/hafner/grading/AutoGradingAction::lambda$run$1 + + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + lambda$run$2 + (Ljava/lang/String;)Ljava/nio/file/Path; + 89 + org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator + + 7 + + + 1 + + + replaced return value with null for edu/hm/hafner/grading/AutoGradingAction::lambda$run$2 + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + lambda$run$3 + (Ljava/nio/file/Path;)Z + 90 + org.pitest.mutationtest.engine.gregor.mutators.returns.BooleanFalseReturnValsMutator + + 7 + + + 1 + + + replaced boolean return with false for edu/hm/hafner/grading/AutoGradingAction::lambda$run$3 + + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + lambda$run$3 + (Ljava/nio/file/Path;)Z + 90 + org.pitest.mutationtest.engine.gregor.mutators.returns.BooleanTrueReturnValsMutator + + 7 + + + 1 + + + replaced boolean return with true for edu/hm/hafner/grading/AutoGradingAction::lambda$run$3 + + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + main + ([Ljava/lang/String;)V + 41 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 6 + + + 1 + + + removed call to edu/hm/hafner/grading/AutoGradingAction::run + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + readDefaultConfiguration + ()Ljava/lang/String; + 159 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 11 + + + 2 + + + edu.hm.hafner.grading.AutoGradingRunnerTest.[engine:junit-jupiter]/[class:edu.hm.hafner.grading.AutoGradingRunnerTest]/[method:shouldReadDefaultConfigurationIfEnvironmentIsNotSet()] + + negated conditional + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + readDefaultConfiguration + ()Ljava/lang/String; + 165 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 36 + + + 9 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + readDefaultConfiguration + ()Ljava/lang/String; + 162 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 27 + + + 8 + + + edu.hm.hafner.grading.AutoGradingRunnerTest.[engine:junit-jupiter]/[class:edu.hm.hafner.grading.AutoGradingRunnerTest]/[method:shouldReadDefaultConfigurationIfEnvironmentIsNotSet()] + + replaced return value with "" for + edu/hm/hafner/grading/AutoGradingAction::readDefaultConfiguration + + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 48 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 20 + + + 2 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 49 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 25 + + + 3 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 50 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 30 + + + 4 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 53 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 43 + + + 7 + + + removed call to edu/hm/hafner/grading/LogHandler::print + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 55 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 48 + + + 8 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 60 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 61 + + + 11 + + + removed call to edu/hm/hafner/grading/AggregatedScore::gradeTests + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 61 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 65 + + + 12 + + + removed call to edu/hm/hafner/grading/LogHandler::print + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 63 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 70 + + + 13 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 65 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 77 + + + 15 + + + removed call to edu/hm/hafner/grading/AggregatedScore::gradeCoverage + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 66 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 81 + + + 16 + + + removed call to edu/hm/hafner/grading/LogHandler::print + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 68 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 86 + + + 17 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 70 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 93 + + + 19 + + + removed call to edu/hm/hafner/grading/AggregatedScore::gradeAnalysis + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 71 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 97 + + + 20 + + + removed call to edu/hm/hafner/grading/LogHandler::print + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 73 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 102 + + + 21 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 75 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 107 + + + 22 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 82 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 141 + + + 32 + + + removed call to java/util/stream/Stream::forEach + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 84 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 146 + + + 33 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 91 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 180 + + + 43 + + + removed call to java/util/stream/Stream::forEach + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 93 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 185 + + + 44 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 97 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 198 + + + 47 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 99 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 228 + + + 54 + + + removed call to edu/hm/hafner/grading/github/GitHubPullRequestWriter::addComment + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 112 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 261 + + + 59 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 113 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 267 + + + 61 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 116 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 302 + + + 68 + + + removed call to edu/hm/hafner/grading/github/GitHubPullRequestWriter::addComment + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 124 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 308 + + + 69 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 125 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 313 + + + 70 + + + removed call to java/io/PrintStream::println + + + AutoGradingAction.java + edu.hm.hafner.grading.AutoGradingAction + run + ()V + 126 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 318 + + + 71 + + + removed call to java/io/PrintStream::println + + + LogHandler.java + edu.hm.hafner.grading.LogHandler + getSizeOfErrorMessages + ()I + 42 + org.pitest.mutationtest.engine.gregor.mutators.returns.PrimitiveReturnsMutator + + 7 + + + 2 + + + replaced int return with 0 for edu/hm/hafner/grading/LogHandler::getSizeOfErrorMessages + + + LogHandler.java + edu.hm.hafner.grading.LogHandler + getSizeOfInfoMessages + ()I + 38 + org.pitest.mutationtest.engine.gregor.mutators.returns.PrimitiveReturnsMutator + + 7 + + + 2 + + + replaced int return with 0 for edu/hm/hafner/grading/LogHandler::getSizeOfInfoMessages + + + LogHandler.java + edu.hm.hafner.grading.LogHandler + print + ()V + 46 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 4 + + + 0 + + + removed call to edu/hm/hafner/grading/LogHandler::printInfoMessages + + + LogHandler.java + edu.hm.hafner.grading.LogHandler + print + ()V + 47 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 8 + + + 1 + + + removed call to edu/hm/hafner/grading/LogHandler::printErrorMessages + + + LogHandler.java + edu.hm.hafner.grading.LogHandler + printErrorMessages + ()V + 60 + org.pitest.mutationtest.engine.gregor.mutators.ConditionalsBoundaryMutator + + 11 + + + 1 + + + changed conditional boundary + + + LogHandler.java + edu.hm.hafner.grading.LogHandler + printErrorMessages + ()V + 60 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 11 + + + 1 + + + negated conditional + + + LogHandler.java + edu.hm.hafner.grading.LogHandler + printErrorMessages + ()V + 60 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 14 + + + 2 + + + negated conditional + + + LogHandler.java + edu.hm.hafner.grading.LogHandler + printErrorMessages + ()V + 61 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 30 + + + 6 + + + removed call to java/util/List::forEach + + + LogHandler.java + edu.hm.hafner.grading.LogHandler + printInfoMessages + ()V + 52 + org.pitest.mutationtest.engine.gregor.mutators.ConditionalsBoundaryMutator + + 11 + + + 1 + + + changed conditional boundary + + + LogHandler.java + edu.hm.hafner.grading.LogHandler + printInfoMessages + ()V + 52 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 11 + + + 1 + + + negated conditional + + + LogHandler.java + edu.hm.hafner.grading.LogHandler + printInfoMessages + ()V + 52 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 14 + + + 2 + + + negated conditional + + + LogHandler.java + edu.hm.hafner.grading.LogHandler + printInfoMessages + ()V + 53 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 30 + + + 6 + + + removed call to java/util/List::forEach + + + ReportFinder.java + edu.hm.hafner.grading.ReportFinder + find + (Ljava/lang/String;)Ljava/util/List; + 79 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 7 + + + 1 + + + replaced return value with Collections.emptyList for edu/hm/hafner/grading/ReportFinder::find + + + + ReportFinder.java + edu.hm.hafner.grading.ReportFinder + find + (Ljava/lang/String;Ljava/lang/String;)Ljava/util/List; + 63 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 33 + + + 6 + + + removed call to java/io/PrintStream::println + + + ReportFinder.java + edu.hm.hafner.grading.ReportFinder + find + (Ljava/lang/String;Ljava/lang/String;)Ljava/util/List; + 60 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 22 + + + 4 + + + edu.hm.hafner.grading.ReportFinderTest.[engine:junit-jupiter]/[class:edu.hm.hafner.grading.ReportFinderTest]/[method:shouldCreateAffectedFilesReport()] + + replaced return value with Collections.emptyList for edu/hm/hafner/grading/ReportFinder::find + + + + ReportFinder.java + edu.hm.hafner.grading.ReportFinder + find + (Ljava/lang/String;Ljava/lang/String;)Ljava/util/List; + 65 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 39 + + + 8 + + + replaced return value with Collections.emptyList for edu/hm/hafner/grading/ReportFinder::find + + + + ReportFinder.java + edu.hm.hafner.grading.ReportFinder + getEnv + (Ljava/lang/String;)Ljava/lang/String; + 29 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 6 + + + 2 + + + replaced return value with "" for edu/hm/hafner/grading/ReportFinder::getEnv + + + ReportFinder.java + edu.hm.hafner.grading.ReportFinder + lambda$renderLinks$0 + (Ljava/nio/file/Path;)Ljava/lang/String; + 85 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 32 + + + 3 + + + edu.hm.hafner.grading.ReportFinderTest.[engine:junit-jupiter]/[class:edu.hm.hafner.grading.ReportFinderTest]/[method:shouldCreateAffectedFilesReport()] + + replaced return value with "" for edu/hm/hafner/grading/ReportFinder::lambda$renderLinks$0 + + + + ReportFinder.java + edu.hm.hafner.grading.ReportFinder + renderLinks + (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; + 84 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 27 + + + 5 + + + edu.hm.hafner.grading.ReportFinderTest.[engine:junit-jupiter]/[class:edu.hm.hafner.grading.ReportFinderTest]/[method:shouldCreateAffectedFilesReport()] + + replaced return value with "" for edu/hm/hafner/grading/ReportFinder::renderLinks + + + + ConsoleCoverageReportFactory.java + edu.hm.hafner.grading.ConsoleCoverageReportFactory + create + + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ledu/hm/hafner/coverage/Node; + + 37 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 103 + + + 24 + + + negated conditional + + + ConsoleCoverageReportFactory.java + edu.hm.hafner.grading.ConsoleCoverageReportFactory + create + + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ledu/hm/hafner/coverage/Node; + + 31 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 63 + + + 15 + + + removed call to edu/hm/hafner/util/FilteredLog::logInfo + + + ConsoleCoverageReportFactory.java + edu.hm.hafner.grading.ConsoleCoverageReportFactory + create + + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ledu/hm/hafner/coverage/Node; + + 36 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 97 + + + 21 + + + removed call to edu/hm/hafner/util/FilteredLog::logInfo + + + ConsoleCoverageReportFactory.java + edu.hm.hafner.grading.ConsoleCoverageReportFactory + create + + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ledu/hm/hafner/coverage/Node; + + 42 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 121 + + + 28 + + + removed call to edu/hm/hafner/coverage/ContainerNode::addChild + + + ConsoleCoverageReportFactory.java + edu.hm.hafner.grading.ConsoleCoverageReportFactory + create + + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ledu/hm/hafner/coverage/Node; + + 38 + org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator + + 107 + + + 25 + + + replaced return value with null for edu/hm/hafner/grading/ConsoleCoverageReportFactory::create + + + + ConsoleCoverageReportFactory.java + edu.hm.hafner.grading.ConsoleCoverageReportFactory + create + + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ledu/hm/hafner/coverage/Node; + + 43 + org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator + + 125 + + + 29 + + + replaced return value with null for edu/hm/hafner/grading/ConsoleCoverageReportFactory::create + + + + ConsoleCoverageReportFactory.java + edu.hm.hafner.grading.ConsoleCoverageReportFactory + extractMetric + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/coverage/Node;)Ljava/lang/String; + + 47 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 20 + + + 6 + + + replaced return value with "" for + edu/hm/hafner/grading/ConsoleCoverageReportFactory::extractMetric + + + + ReportFactory.java + edu.hm.hafner.grading.ReportFactory + findFiles + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ljava/util/List; + + 21 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 36 + + + 7 + + + negated conditional + + + ReportFactory.java + edu.hm.hafner.grading.ReportFactory + findFiles + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ljava/util/List; + + 17 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 21 + + + 2 + + + removed call to edu/hm/hafner/util/FilteredLog::logInfo + + + ReportFactory.java + edu.hm.hafner.grading.ReportFactory + findFiles + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ljava/util/List; + + 26 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 65 + + + 13 + + + removed call to java/util/Collections::sort + + + ReportFactory.java + edu.hm.hafner.grading.ReportFactory + findFiles + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ljava/util/List; + + 27 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 69 + + + 14 + + + replaced return value with Collections.emptyList for edu/hm/hafner/grading/ReportFactory::findFiles + + + + ReportFinder.java + edu.hm.hafner.grading.ReportFinder$PathMatcherFileVisitor + getMatches + ()Ljava/util/List; + 108 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 5 + + + 0 + + + edu.hm.hafner.grading.ReportFinderTest.[engine:junit-jupiter]/[class:edu.hm.hafner.grading.ReportFinderTest]/[method:shouldCreateAffectedFilesReport()] + + replaced return value with Collections.emptyList for + edu/hm/hafner/grading/ReportFinder$PathMatcherFileVisitor::getMatches + + + + ReportFinder.java + edu.hm.hafner.grading.ReportFinder$PathMatcherFileVisitor + visitFile + + (Ljava/nio/file/Path;Ljava/nio/file/attribute/BasicFileAttributes;)Ljava/nio/file/FileVisitResult; + + 113 + org.pitest.mutationtest.engine.gregor.mutators.NegateConditionalsMutator + + 7 + + + 1 + + + edu.hm.hafner.grading.ReportFinderTest.[engine:junit-jupiter]/[class:edu.hm.hafner.grading.ReportFinderTest]/[method:shouldCreateAffectedFilesReport()] + + negated conditional + + + ReportFinder.java + edu.hm.hafner.grading.ReportFinder$PathMatcherFileVisitor + visitFile + + (Ljava/nio/file/Path;Ljava/nio/file/attribute/BasicFileAttributes;)Ljava/nio/file/FileVisitResult; + + 116 + org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator + + 19 + + + 4 + + + edu.hm.hafner.grading.ReportFinderTest.[engine:junit-jupiter]/[class:edu.hm.hafner.grading.ReportFinderTest]/[method:shouldCreateAffectedFilesReport()] + + replaced return value with null for + edu/hm/hafner/grading/ReportFinder$PathMatcherFileVisitor::visitFile + + + + ReportFinder.java + edu.hm.hafner.grading.ReportFinder$PathMatcherFileVisitor + visitFileFailed + (Ljava/nio/file/Path;Ljava/io/IOException;)Ljava/nio/file/FileVisitResult; + 121 + org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator + + 4 + + + 0 + + + edu.hm.hafner.grading.ReportFinderTest.[engine:junit-jupiter]/[class:edu.hm.hafner.grading.ReportFinderTest]/[method:shouldFindTestReports()] + + replaced return value with null for + edu/hm/hafner/grading/ReportFinder$PathMatcherFileVisitor::visitFileFailed + + + + ConsoleAnalysisReportFactory.java + edu.hm.hafner.grading.ConsoleAnalysisReportFactory + create + + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ledu/hm/hafner/analysis/Report; + + 27 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 69 + + + 17 + + + removed call to edu/hm/hafner/util/FilteredLog::logInfo + + + ConsoleAnalysisReportFactory.java + edu.hm.hafner.grading.ConsoleAnalysisReportFactory + create + + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ledu/hm/hafner/analysis/Report; + + 31 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 102 + + + 23 + + + removed call to edu/hm/hafner/util/FilteredLog::logInfo + + + ConsoleAnalysisReportFactory.java + edu.hm.hafner.grading.ConsoleAnalysisReportFactory + create + + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ledu/hm/hafner/analysis/Report; + + 32 + org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator + + 106 + + + 24 + + + replaced return value with null for edu/hm/hafner/grading/ConsoleAnalysisReportFactory::create + + + + ConsoleTestReportFactory.java + edu.hm.hafner.grading.ConsoleTestReportFactory + create + + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ledu/hm/hafner/coverage/Node; + + 24 + org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator + + 56 + + + 10 + + + removed call to edu/hm/hafner/util/FilteredLog::logInfo + + + ConsoleTestReportFactory.java + edu.hm.hafner.grading.ConsoleTestReportFactory + create + + (Ledu/hm/hafner/grading/ToolConfiguration;Ledu/hm/hafner/util/FilteredLog;)Ledu/hm/hafner/coverage/Node; + + 27 + org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator + + 60 + + + 11 + + + replaced return value with null for edu/hm/hafner/grading/ConsoleTestReportFactory::create + + + + FileNameRenderer.java + edu.hm.hafner.grading.FileNameRenderer + getFileName + (Ledu/hm/hafner/analysis/Report;Ljava/lang/String;)Ljava/lang/String; + 15 + org.pitest.mutationtest.engine.gregor.mutators.returns.EmptyObjectReturnValsMutator + + 9 + + + 3 + + + replaced return value with "" for edu/hm/hafner/grading/FileNameRenderer::getFileName + + + diff --git a/src/test/resources/pmd/pmd-ignores.xml b/src/test/resources/pmd/pmd-ignores.xml new file mode 100644 index 0000000..5457242 --- /dev/null +++ b/src/test/resources/pmd/pmd-ignores.xml @@ -0,0 +1,193 @@ + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + +Consider using varargs for methods or constructors which take an array the last parameter. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + +The method 'main(String...)' has a cognitive complexity of 16, current threshold is 15 + + +These nested if statements could be combined + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + +Avoid using Literals in Conditional Statements + + +Consider using varargs for methods or constructors which take an array the last parameter. + + + + +All methods are static. Consider using a utility class instead. Alternatively, you could add a private constructor or make the class abstract to silence this warning. + + + + +This abstract class does not have any abstract methods + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + + +Linguistics Antipattern - The method 'shouldSolveAssignment' indicates linguistically it returns a boolean, but it returns 'Stream' + + + diff --git a/src/test/resources/pmd/pmd.xml b/src/test/resources/pmd/pmd.xml new file mode 100644 index 0000000..d25a8e7 --- /dev/null +++ b/src/test/resources/pmd/pmd.xml @@ -0,0 +1,39 @@ + + + + +This abstract class does not have any abstract methods + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/spotbugs/spotbugsXml.xml b/src/test/resources/spotbugs/spotbugsXml.xml new file mode 100644 index 0000000..b4504b4 --- /dev/null +++ b/src/test/resources/spotbugs/spotbugsXml.xml @@ -0,0 +1,370 @@ + + + + /Users/hafner/git/warnings-ng-plugin-devenv/autograding-github-action/target/classes + /Users/hafner/git/warnings-ng-plugin-devenv/autograding-github-action/target/test-classes + /Users/hafner/git/warnings-ng-plugin-devenv/autograding-github-action/target/test-classes + + /Users/hafner/.m2/repository/edu/hm/hafner/autograding-model/3.7.0/autograding-model-3.7.0.jar + + + /Users/hafner/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.16.0/jackson-databind-2.16.0.jar + + + /Users/hafner/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.16.0/jackson-annotations-2.16.0.jar + + + /Users/hafner/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.16.0/jackson-core-2.16.0.jar + + /Users/hafner/.m2/repository/edu/hm/hafner/analysis-model/11.13.0/analysis-model-11.13.0.jar + + /Users/hafner/.m2/repository/org/jsoup/jsoup/1.16.2/jsoup-1.16.2.jar + /Users/hafner/.m2/repository/org/apache/commons/commons-digester3/3.2/commons-digester3-3.2.jar + + /Users/hafner/.m2/repository/cglib/cglib/2.2.2/cglib-2.2.2.jar + /Users/hafner/.m2/repository/commons-logging/commons-logging/1.2/commons-logging-1.2.jar + + + /Users/hafner/.m2/repository/commons-beanutils/commons-beanutils/1.9.4/commons-beanutils-1.9.4.jar + + + /Users/hafner/.m2/repository/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar + + /Users/hafner/.m2/repository/org/apache/commons/commons-text/1.10.0/commons-text-1.10.0.jar + + + /Users/hafner/.m2/repository/se/bjurr/violations/violations-lib/1.156.7/violations-lib-1.156.7.jar + + /Users/hafner/.m2/repository/com/j2html/j2html/1.4.0/j2html-1.4.0.jar + /Users/hafner/.m2/repository/xerces/xercesImpl/2.12.2/xercesImpl-2.12.2.jar + /Users/hafner/.m2/repository/xml-apis/xml-apis/1.4.01/xml-apis-1.4.01.jar + /Users/hafner/.m2/repository/org/ow2/asm/asm/9.6/asm-9.6.jar + /Users/hafner/.m2/repository/com/github/spotbugs/spotbugs/4.8.0/spotbugs-4.8.0.jar + + /Users/hafner/.m2/repository/org/ow2/asm/asm-analysis/9.6/asm-analysis-9.6.jar + + /Users/hafner/.m2/repository/org/ow2/asm/asm-commons/9.6/asm-commons-9.6.jar + /Users/hafner/.m2/repository/org/ow2/asm/asm-tree/9.6/asm-tree-9.6.jar + /Users/hafner/.m2/repository/org/ow2/asm/asm-util/9.6/asm-util-9.6.jar + + /Users/hafner/.m2/repository/com/github/stephenc/jcip/jcip-annotations/1.0-1/jcip-annotations-1.0-1.jar + + /Users/hafner/.m2/repository/org/dom4j/dom4j/2.1.4/dom4j-2.1.4.jar + /Users/hafner/.m2/repository/com/google/code/gson/gson/2.10.1/gson-2.10.1.jar + /Users/hafner/.m2/repository/jaxen/jaxen/2.0.0/jaxen-2.0.0.jar + /Users/hafner/.m2/repository/net/sf/saxon/Saxon-HE/12.3/Saxon-HE-12.3.jar + /Users/hafner/.m2/repository/org/xmlresolver/xmlresolver/5.2.0/xmlresolver-5.2.0.jar + + + /Users/hafner/.m2/repository/org/apache/httpcomponents/client5/httpclient5/5.1.3/httpclient5-5.1.3.jar + + + /Users/hafner/.m2/repository/org/apache/httpcomponents/core5/httpcore5-h2/5.1.3/httpcore5-h2-5.1.3.jar + + /Users/hafner/.m2/repository/commons-codec/commons-codec/1.15/commons-codec-1.15.jar + + + /Users/hafner/.m2/repository/org/apache/httpcomponents/core5/httpcore5/5.1.3/httpcore5-5.1.3.jar + + /Users/hafner/.m2/repository/org/xmlresolver/xmlresolver/5.2.0/xmlresolver-5.2.0-data.jar + + /Users/hafner/.m2/repository/org/apache/logging/log4j/log4j-core/2.20.0/log4j-core-2.20.0.jar + + /Users/hafner/.m2/repository/org/apache/logging/log4j/log4j-api/2.20.0/log4j-api-2.20.0.jar + + /Users/hafner/.m2/repository/org/apache/bcel/bcel/6.7.0/bcel-6.7.0.jar + /Users/hafner/.m2/repository/net/sourceforge/pmd/pmd-core/6.55.0/pmd-core-6.55.0.jar + + /Users/hafner/.m2/repository/org/antlr/antlr4-runtime/4.7.2/antlr4-runtime-4.7.2.jar + + /Users/hafner/.m2/repository/com/beust/jcommander/1.82/jcommander-1.82.jar + /Users/hafner/.m2/repository/net/sourceforge/pmd/pmd-java/6.55.0/pmd-java-6.55.0.jar + + /Users/hafner/.m2/repository/org/json/json/20231013/json-20231013.jar + /Users/hafner/.m2/repository/net/minidev/json-smart/2.5.0/json-smart-2.5.0.jar + + /Users/hafner/.m2/repository/net/minidev/accessors-smart/2.5.0/accessors-smart-2.5.0.jar + + /Users/hafner/.m2/repository/org/slf4j/slf4j-api/2.0.9/slf4j-api-2.0.9.jar + /Users/hafner/.m2/repository/edu/hm/hafner/coverage-model/0.36.0/coverage-model-0.36.0.jar + + /Users/hafner/.m2/repository/org/kohsuke/github-api/1.318/github-api-1.318.jar + + /Users/hafner/.m2/repository/commons-io/commons-io/2.15.1/commons-io-2.15.1.jar + + /Users/hafner/.m2/repository/org/apache/commons/commons-lang3/3.14.0/commons-lang3-3.14.0.jar + + /Users/hafner/.m2/repository/org/testcontainers/testcontainers/1.19.3/testcontainers-1.19.3.jar + + /Users/hafner/.m2/repository/junit/junit/4.13.2/junit-4.13.2.jar + /Users/hafner/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar + + + /Users/hafner/.m2/repository/org/apache/commons/commons-compress/1.24.0/commons-compress-1.24.0.jar + + /Users/hafner/.m2/repository/org/rnorth/duct-tape/duct-tape/1.0.8/duct-tape-1.0.8.jar + + /Users/hafner/.m2/repository/org/jetbrains/annotations/17.0.0/annotations-17.0.0.jar + + + /Users/hafner/.m2/repository/com/github/docker-java/docker-java-api/3.3.4/docker-java-api-3.3.4.jar + + + /Users/hafner/.m2/repository/com/github/docker-java/docker-java-transport-zerodep/3.3.4/docker-java-transport-zerodep-3.3.4.jar + + + /Users/hafner/.m2/repository/com/github/docker-java/docker-java-transport/3.3.4/docker-java-transport-3.3.4.jar + + /Users/hafner/.m2/repository/net/java/dev/jna/jna/5.13.0/jna-5.13.0.jar + /Users/hafner/.m2/repository/org/testcontainers/junit-jupiter/1.19.3/junit-jupiter-1.19.3.jar + + + /Users/hafner/.m2/repository/com/github/spotbugs/spotbugs-annotations/4.8.2/spotbugs-annotations-4.8.2.jar + + + /Users/hafner/.m2/repository/com/google/errorprone/error_prone_annotations/2.23.0/error_prone_annotations-2.23.0.jar + + /Users/hafner/.m2/repository/one/util/streamex/0.8.2/streamex-0.8.2.jar + /Users/hafner/.m2/repository/edu/hm/hafner/codingstyle/3.28.0/codingstyle-3.28.0.jar + + + /Users/hafner/.m2/repository/org/junit/jupiter/junit-jupiter-api/5.10.1/junit-jupiter-api-5.10.1.jar + + /Users/hafner/.m2/repository/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar + + + /Users/hafner/.m2/repository/org/junit/platform/junit-platform-commons/1.10.1/junit-platform-commons-1.10.1.jar + + /Users/hafner/.m2/repository/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar + + + /Users/hafner/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.10.1/junit-jupiter-engine-5.10.1.jar + + + /Users/hafner/.m2/repository/org/junit/platform/junit-platform-engine/1.10.1/junit-platform-engine-1.10.1.jar + + + /Users/hafner/.m2/repository/org/junit/platform/junit-platform-launcher/1.10.1/junit-platform-launcher-1.10.1.jar + + + /Users/hafner/.m2/repository/org/junit/jupiter/junit-jupiter-params/5.10.1/junit-jupiter-params-5.10.1.jar + + /Users/hafner/.m2/repository/org/junit-pioneer/junit-pioneer/2.2.0/junit-pioneer-2.2.0.jar + + /Users/hafner/.m2/repository/org/mockito/mockito-core/5.7.0/mockito-core-5.7.0.jar + + /Users/hafner/.m2/repository/net/bytebuddy/byte-buddy/1.14.10/byte-buddy-1.14.10.jar + + /Users/hafner/.m2/repository/net/bytebuddy/byte-buddy-agent/1.14.9/byte-buddy-agent-1.14.9.jar + + /Users/hafner/.m2/repository/org/objenesis/objenesis/3.3/objenesis-3.3.jar + /Users/hafner/.m2/repository/org/assertj/assertj-core/3.24.2/assertj-core-3.24.2.jar + + + /Users/hafner/.m2/repository/com/tngtech/archunit/archunit-junit5/1.2.0/archunit-junit5-1.2.0.jar + + + /Users/hafner/.m2/repository/com/tngtech/archunit/archunit-junit5-api/1.2.0/archunit-junit5-api-1.2.0.jar + + /Users/hafner/.m2/repository/com/tngtech/archunit/archunit/1.2.0/archunit-1.2.0.jar + + + /Users/hafner/.m2/repository/com/tngtech/archunit/archunit-junit5-engine/1.2.0/archunit-junit5-engine-1.2.0.jar + + + /Users/hafner/.m2/repository/com/tngtech/archunit/archunit-junit5-engine-api/1.2.0/archunit-junit5-engine-api-1.2.0.jar + + /Users/hafner/.m2/repository/org/slf4j/slf4j-simple/2.0.9/slf4j-simple-2.0.9.jar + + + /Users/hafner/.m2/repository/nl/jqno/equalsverifier/equalsverifier/3.15.4/equalsverifier-3.15.4.jar + + /Users/hafner/.m2/repository/edu/hm/hafner/codingstyle/3.28.0/codingstyle-3.28.0-tests.jar + + + /Users/hafner/git/warnings-ng-plugin-devenv/autograding-github-action/src/main/java + /Users/hafner/git/warnings-ng-plugin-devenv/autograding-github-action/target/generated-sources/annotations + + /Users/hafner/git/warnings-ng-plugin-devenv/autograding-github-action/src/test/java + + /Users/hafner/git/warnings-ng-plugin-devenv/autograding-github-action/target/generated-test-sources/test-annotations + + /Users/hafner/git/warnings-ng-plugin-devenv/autograding-github-action/target + + + Usage of GetResource may be unsafe if class is extended + Usage of GetResource in edu.hm.hafner.grading.AutoGradingAction.readDefaultConfiguration() may be unsafe if class is extended + + + + At AutoGradingAction.java:[lines 33-166] + + In class edu.hm.hafner.grading.AutoGradingAction + + + + In method edu.hm.hafner.grading.AutoGradingAction.readDefaultConfiguration() + + + At AutoGradingAction.java:[line 158] + + + + Bad practice + + + Usage of GetResource may be unsafe if class is extended +
+ + <p>Calling <code>this.getClass().getResource(...)</code> could give + results other than expected if this class is extended by a class in + another package.</p> + +
+
+ + Unsafe inheritance + + + accept + apply + makeConcatWithConstants + test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +