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 038fd54
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 2 deletions.
@@ -0,0 +1,64 @@
/*
* ScalaCheck
* Copyright (c) 2007-2021 Rickard Nilsson. All rights reserved.
* http://www.scalacheck.org
*
* This software is released under the terms of the Revised BSD License.
* There is NO WARRANTY. See the file LICENSE for the full text.
*/

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
}
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

0 comments on commit 038fd54

Please sign in to comment.