Skip to content

Commit

Permalink
Verify only props matching the given TestSelectors
Browse files Browse the repository at this point in the history
Previously, ScalaCheck ignored the selectors that it receives as input
in the "root task". This prevented users from running only a subset of
properties in a specification by passing their `TestSelector` to
ScalaCheck in a `TaskDef`.

This patch fixes this by having the root task program the execution of
only the requested properties if the `TaskDef` contains only
`TestSelector`s. ScalaCheck's behavior remains unchanged if the
`TaskDef` contains any other kind of `Selector`.
  • Loading branch information
Duhemm committed Jan 17, 2024
1 parent ec41b4c commit ec99639
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,14 @@ private abstract class ScalaCheckRunner extends Runner {
}

def rootTask(td: TaskDef): BaseTask = new BaseTask(td) {
def execute(handler: EventHandler, loggers: Array[Logger]): Array[Task] =
props.map(_._1).toSet.toArray map { name =>
def execute(handler: EventHandler, loggers: Array[Logger]): Array[Task] = {
// If the task contains only `TestSelector`s, then run only these props instead of the whole suite.
val propFilter: String => Boolean =
if (td.selectors().forall(_.isInstanceOf[TestSelector]))
td.selectors().collect { case ts: TestSelector => ts.testName() }.toSet
else
Function.const(true)
props.map(_._1).toSet.filter(propFilter).toArray map { name =>
checkPropTask(
new TaskDef(
td.fullyQualifiedName(),
Expand All @@ -102,6 +108,7 @@ private abstract class ScalaCheckRunner extends Runner {
Array(new TestSelector(name))),
single = true)
}
}
}

def checkPropTask(taskDef: TaskDef, single: Boolean): BaseTask = new BaseTask(taskDef) { self =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.scalacheck

import org.scalacheck.Prop.proved
import sbt.testing.{Selector, SuiteSelector, TaskDef, TestSelector}

object ScalaCheckFrameworkSpecification extends Properties("ScalaCheckFramework") {

private val firstProp = "ScalaCheckFrameworkHelper.first prop"
private val secondProp = "ScalaCheckFrameworkHelper.second prop"
private val thirdProp = "ScalaCheckFrameworkHelper.third prop"


property("all props with SuiteSelector") = {
getPropNamesForSelectors(List(new SuiteSelector)) == List(firstProp, secondProp, thirdProp)
getPropNamesForSelectors(List(new SuiteSelector, new TestSelector(firstProp))) == List(firstProp, secondProp, thirdProp)
getPropNamesForSelectors(List(new SuiteSelector, new TestSelector("no matches"))) == List(firstProp, secondProp, thirdProp)
}

property("only matching props with TestSelector") = {
getPropNamesForSelectors(List(new TestSelector(firstProp))) == List(firstProp)
getPropNamesForSelectors(List(new TestSelector(secondProp))) == List(secondProp)
getPropNamesForSelectors(List(new TestSelector(firstProp), new TestSelector(thirdProp))) == List(firstProp, thirdProp)
getPropNamesForSelectors(List(new TestSelector("no matches"))) == Nil
}

private def getPropNamesForSelectors(selectors: List[Selector]): List[String] = {
val framework = new ScalaCheckFramework()
val runner = framework.runner(Array.empty, Array.empty, getClass.getClassLoader).asInstanceOf[ScalaCheckRunner]
val taskDef = new TaskDef(classOf[ScalaCheckFrameworkSpecificationHelper].getName, framework.fingerprints()(0), true, selectors.toArray)
val baseTask = runner.rootTask(taskDef)
val newTasks = baseTask.execute(null, null)
val propNames = for {
task <- newTasks
selector <- task.taskDef().selectors()
} yield selector.asInstanceOf[TestSelector].testName()
propNames.toList
}
}

class ScalaCheckFrameworkSpecificationHelper extends Properties("ScalaCheckFrameworkHelper") {
property("first prop") = proved
property("second prop") = proved
property("third prop") = proved
}

0 comments on commit ec99639

Please sign in to comment.