Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Comply with html reporter format #160

Merged
merged 48 commits into from Mar 20, 2019
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
460023f
WIP: Start on mapper
legopiraat Aug 6, 2018
93eba12
WIP: First setup to generate classes based on the html reporter spec
legopiraat Aug 9, 2018
86e7c77
Fill in a few more fields
legopiraat Aug 12, 2018
8e3cb2a
Add file source to report structure
legopiraat Aug 12, 2018
f3f6fae
Add plumbing so we can validate the html reporter output against the …
legopiraat Sep 1, 2018
c0b60c7
Merge branch 'master' into HTML-Reporter
legopiraat Sep 20, 2018
b8b7c5e
Merge branch 'HTML-Reporter' into Comply-html-reporter-format
legopiraat Sep 20, 2018
2f6779e
Add names to mutants so we can have it in the html report
legopiraat Sep 20, 2018
55329ce
Merge branch 'Mutant-name-for-html-report' into Comply-html-reporter-…
legopiraat Sep 20, 2018
17680bf
Add html reporter to list of available reporters + add mutator name t…
legopiraat Sep 20, 2018
aa90691
Add test to make sure multiple reporters are invoked when specified
legopiraat Sep 20, 2018
d9153d0
Merge branch 'master' of https://github.com/stryker-mutator/stryker4s…
legopiraat Jan 20, 2019
e081c48
More of the merge
legopiraat Jan 20, 2019
cfc2522
Add location
legopiraat Jan 20, 2019
fbdb58e
Cleanup tests and add schema in resources
hugo-vrijswijk Feb 19, 2019
e00f474
Add test for validating generated json
hugo-vrijswijk Feb 19, 2019
632fe0b
Update everit-json-schema version (using jitpack now)
hugo-vrijswijk Feb 19, 2019
3441459
WIP
hugo-vrijswijk Feb 19, 2019
514dc4f
Merge remote-tracking branch 'origin/master' into Comply-html-reporte…
hugo-vrijswijk Feb 19, 2019
a9ffa5b
Remove Circe parser dependency (no parsing is done, only writing)
hugo-vrijswijk Feb 19, 2019
a548118
Redo html report case classes
hugo-vrijswijk Feb 19, 2019
cf1d7ed
WIP: Add test for mapping validation
hugo-vrijswijk Feb 19, 2019
3abff6b
WIP
hugo-vrijswijk Feb 19, 2019
1a2bf82
Fix rename issue
hugo-vrijswijk Feb 19, 2019
6a9889e
Add new flat structure report schema
hugo-vrijswijk Feb 21, 2019
1b36880
Move reporter to stryker4s.report package and add new report case cla…
hugo-vrijswijk Feb 21, 2019
ab84208
Move tests and replace report json with new version
hugo-vrijswijk Feb 21, 2019
92bdae4
Implement MutantMapper and add tests
hugo-vrijswijk Feb 21, 2019
aa3d36f
Add html report files to resources
hugo-vrijswijk Feb 21, 2019
ab2a0a3
Fix mapper not finding correct file source
hugo-vrijswijk Feb 22, 2019
f92dde3
Fix html reporter
hugo-vrijswijk Feb 22, 2019
f9ac27d
Fix test not finding files
hugo-vrijswijk Feb 22, 2019
6d64b56
Remove stryker4s.conf
Wmaarts Feb 22, 2019
5d818bb
Small refactorings and comments
hugo-vrijswijk Feb 22, 2019
564eb52
Remove unused code
hugo-vrijswijk Feb 22, 2019
a582084
Merge branch 'feat-html-reporter' into Comply-html-reporter-format
hugo-vrijswijk Feb 25, 2019
683435a
Formatting
hugo-vrijswijk Feb 25, 2019
00ec106
Ugly-print json and add test
hugo-vrijswijk Feb 27, 2019
308d05e
Update mutation-test-elements.js to v0.0.7
hugo-vrijswijk Feb 27, 2019
d1cf0bd
Remove generated sources, and fetch them as a dependency from webjars…
hugo-vrijswijk Mar 17, 2019
36a6916
Merge remote-tracking branch 'origin/master' into Comply-html-reporte…
hugo-vrijswijk Mar 17, 2019
ccddc52
Move report modelclasses into single file
hugo-vrijswijk Mar 17, 2019
faa01e5
Small renaming in MutantRunResultMapper
hugo-vrijswijk Mar 17, 2019
bfc5431
Fix and simplify MutantRunResultMapperTest
hugo-vrijswijk Mar 17, 2019
34eadd4
Edit html config documentation
hugo-vrijswijk Mar 17, 2019
d2b75d2
Fix test
hugo-vrijswijk Mar 17, 2019
cc072dc
Update to v1.0.1 of mutation-testing-report
hugo-vrijswijk Mar 18, 2019
40ec153
Merge remote-tracking branch 'origin/master' into Comply-html-reporte…
hugo-vrijswijk Mar 20, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions core/src/main/resources/html-report/index.html
@@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<body>
<mutation-test-report-app src="mutation-report.json"></mutation-test-report-app>
<script src="mutation-test-elements.js"></script>
</body>

</html>
5,823 changes: 5,823 additions & 0 deletions core/src/main/resources/html-report/mutation-test-elements.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion core/src/main/scala/stryker4s/Stryker4s.scala
Expand Up @@ -5,7 +5,7 @@ import stryker4s.config.Config
import stryker4s.mutants.Mutator
import stryker4s.mutants.findmutants.SourceCollector
import stryker4s.run.MutantRunner
import stryker4s.run.report.Reporter
import stryker4s.report.Reporter
import stryker4s.run.threshold.{ScoreStatus, ThresholdChecker}

class Stryker4s(fileCollector: SourceCollector, mutator: Mutator, runner: MutantRunner, reporter: Reporter)(
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/stryker4s/config/Config.scala
Expand Up @@ -3,7 +3,7 @@ package stryker4s.config
import better.files._
import org.apache.logging.log4j.Level
import pureconfig.ConfigWriter
import stryker4s.run.report.{ConsoleReporter, MutantRunReporter}
import stryker4s.report.{ConsoleReporter, MutantRunReporter}

case class Config(mutate: Seq[String] = Seq("**/main/scala/**/*.scala"),
baseDir: File = File.currentWorkingDirectory,
Expand Down
Expand Up @@ -7,7 +7,7 @@ import grizzled.slf4j.Logging
import org.apache.logging.log4j.Level
import pureconfig.ConfigReader
import stryker4s.config.ExcludedMutations
import stryker4s.run.report.{ConsoleReporter, MutantRunReporter}
import stryker4s.report.{ConsoleReporter, HtmlReporter, MutantRunReporter}

trait ConfigReaderImplicits extends Logging {

Expand All @@ -23,6 +23,7 @@ trait ConfigReaderImplicits extends Logging {
private[config] implicit val toReporterList: ConfigReader[MutantRunReporter] =
ConfigReader[String] map {
case MutantRunReporter.`consoleReporter` => new ConsoleReporter
case MutantRunReporter.`htmlReporter` => new HtmlReporter
}
private[config] implicit val exclusions: ConfigReader[ExcludedMutations] =
ConfigReader[List[String]] map (exclusions => ExcludedMutations(exclusions.toSet))
Expand Down
Expand Up @@ -7,7 +7,7 @@ import com.typesafe.config.ConfigRenderOptions
import org.apache.logging.log4j.Level
import pureconfig.ConfigWriter
import stryker4s.config.ExcludedMutations
import stryker4s.run.report.{ConsoleReporter, MutantRunReporter}
import stryker4s.report.{ConsoleReporter, MutantRunReporter}

object ConfigWriterImplicits {

Expand Down
@@ -1,4 +1,4 @@
package stryker4s.run.report
package stryker4s.report

import java.lang.System.lineSeparator

Expand Down
13 changes: 13 additions & 0 deletions core/src/main/scala/stryker4s/report/HtmlReporter.scala
@@ -0,0 +1,13 @@
package stryker4s.report
import stryker4s.config.Config
import stryker4s.model.MutantRunResults
import stryker4s.report.mapper.MutantRunResultMapper

class HtmlReporter extends MutantRunReporter with MutantRunResultMapper {

override def report(runResults: MutantRunResults)(implicit config: Config): Unit = {
val mapped = toReport(runResults).toJson

println(mapped)
}
}
@@ -1,4 +1,4 @@
package stryker4s.run.report
package stryker4s.report

import stryker4s.config.Config
import stryker4s.model.MutantRunResults
Expand All @@ -9,4 +9,5 @@ trait MutantRunReporter {

object MutantRunReporter {
val consoleReporter: String = "console"
val htmlReporter: String = "html"
}
@@ -1,4 +1,4 @@
package stryker4s.run.report
package stryker4s.report

import stryker4s.config.Config
import stryker4s.model.MutantRunResults
Expand Down
@@ -0,0 +1,60 @@
package stryker4s.report.mapper
import java.nio.file.Path

import stryker4s.config.{Config, Thresholds => ConfigThresholds}
import stryker4s.model._
import stryker4s.report.model.MutantStatus.MutantStatus
import stryker4s.report.model._

trait MutantRunResultMapper {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a couple of thoughts about this trait.

  1. There's one test that covers all the methods, shouldn't we split this up more? That way if a test fails it's easier to identify where the bug is, but I'm not sure how important that is.
  2. If we're not going to do nr 1, all of these methods can be marked private except toReport, if I'm correct.
  3. The method names slightly throw me off. i.e. toLocation makes more sense as an extension method. Now for example you're calling toMutantStatus, but I'm thinking: "you're going to MutantStatus... from where exactly?" if that makes sense. To me something like mapRunResultToMutantStatus makes more sense.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1. There's one test that covers all the methods, shouldn't we split this up more? That way if a test fails it's easier to identify where the bug is, but I'm not sure how important that is.

I agree. The single test is a bit massive. The thing is though is that the 'top' map function calls the other functions anyway. So then having tests for the 'smaller' functions is a bit redundant

3. The method names slightly throw me off. i.e. `toLocation` makes more sense as an extension method. Now for example you're calling `toMutantStatus`, but I'm thinking: "you're going to MutantStatus... from where exactly?" if that makes sense. To me something like `mapRunResultToMutantStatus` makes more sense.

Hmm, I feel like the "from where" is already apparent from it being given as a parameter (as well as the signature). Having names like mapRunResultToMutantStatus will get pretty big and unreadable. I agree the names could be better though


private val schemaVersion = "1"

def toReport(mutantRunResults: MutantRunResults)(implicit config: Config): MutationTestReport = MutationTestReport(
schemaVersion,
toThreshold(config.thresholds),
toFiles(mutantRunResults.results.toSeq)
)

def toThreshold(thresholds: ConfigThresholds): Thresholds =
Thresholds(high = thresholds.high, low = thresholds.low)

def toFiles(results: Seq[MutantRunResult])(implicit config: Config): Map[String, MutationTestResult] =
results groupBy (_.fileSubPath) map {
case (path, runResults) => path.toString.replace('\\', '/') -> toMutationTestResults(runResults)
}

def toMutationTestResults(runResults: Seq[MutantRunResult])(implicit config: Config): MutationTestResult =
MutationTestResult(
fileContentAsString(runResults.head.fileSubPath),
runResults.map(toMutantRunResult)
)

def toMutantRunResult(runResult: MutantRunResult): MutantResult = {
hugo-vrijswijk marked this conversation as resolved.
Show resolved Hide resolved
val mutant = runResult.mutant
MutantResult(
mutant.id.toString,
mutant.mutationType.mutationName,
mutant.mutated.syntax,
toLocation(mutant.original.pos),
toMutantStatus(runResult)
)
}

def toLocation(pos: scala.meta.inputs.Position): Location = Location(
start = Position(line = pos.startLine + 1, column = pos.startColumn + 1),
end = Position(line = pos.endLine + 1, column = pos.endColumn + 1)
)

def toMutantStatus(mutant: MutantRunResult): MutantStatus = mutant match {
case _: Survived => MutantStatus.Survived
case _: Killed => MutantStatus.Killed
case _: NoCoverage => MutantStatus.NoCoverage
case _: TimedOut => MutantStatus.Timeout
case _: Error => MutantStatus.CompileError
}

private[this] def fileContentAsString(path: Path)(implicit config: Config): String =
(config.baseDir / path.toString).contentAsString

}
3 changes: 3 additions & 0 deletions core/src/main/scala/stryker4s/report/model/Location.scala
@@ -0,0 +1,3 @@
package stryker4s.report.model

final case class Location(start: Position, end: Position)
8 changes: 8 additions & 0 deletions core/src/main/scala/stryker4s/report/model/MutantResult.scala
@@ -0,0 +1,8 @@
package stryker4s.report.model
import stryker4s.report.model.MutantStatus.MutantStatus

final case class MutantResult(id: String,
mutatorName: String,
replacement: String,
location: Location,
status: MutantStatus)
6 changes: 6 additions & 0 deletions core/src/main/scala/stryker4s/report/model/MutantStatus.scala
@@ -0,0 +1,6 @@
package stryker4s.report.model

object MutantStatus extends Enumeration {
type MutantStatus = Value
val Killed, Survived, NoCoverage, CompileError, Timeout = Value
}
@@ -0,0 +1,16 @@
package stryker4s.report.model
import io.circe.{Encoder, Json}
import stryker4s.report.model.MutantStatus.MutantStatus

final case class MutationTestReport(schemaVersion: String,
thresholds: Thresholds,
files: Map[String, MutationTestResult]) {

private implicit val encoder: Encoder[MutantStatus] = Encoder.enumEncoder(MutantStatus)

def toJson: Json = {
import io.circe.generic.auto._
import io.circe.syntax._
this.asJson
}
}
@@ -0,0 +1,3 @@
package stryker4s.report.model

final case class MutationTestResult(source: String, mutants: Seq[MutantResult], language: String = "scala")
3 changes: 3 additions & 0 deletions core/src/main/scala/stryker4s/report/model/Position.scala
@@ -0,0 +1,3 @@
package stryker4s.report.model

final case class Position(line: Int, column: Int)
hugo-vrijswijk marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 3 additions & 0 deletions core/src/main/scala/stryker4s/report/model/Thresholds.scala
@@ -0,0 +1,3 @@
package stryker4s.report.model

final case class Thresholds(high: Int, low: Int)
2 changes: 1 addition & 1 deletion core/src/main/scala/stryker4s/run/Stryker4sRunner.scala
Expand Up @@ -7,7 +7,7 @@ import stryker4s.mutants.applymutants.ActiveMutationContext.ActiveMutationContex
import stryker4s.mutants.applymutants.{MatchBuilder, StatementTransformer}
import stryker4s.mutants.findmutants.{FileCollector, MutantFinder, MutantMatcher, SourceCollector}
import stryker4s.run.process.ProcessRunner
import stryker4s.run.report.Reporter
import stryker4s.report.Reporter
import stryker4s.run.threshold.ScoreStatus

import scala.meta.internal.tokenizers.PlatformTokenizerCache
Expand Down