2016-04-12 15 views
0

SBTタグを使用して、いくつかの仕様の同時実行を制御したいと考えています。SBTタグを使用してspecs2テストの同時実行を制御する

たとえば、データベースを同時に使用する1つ以上のテストは不要です。 ScalaTestで

、私は同時に実行されないでしょう

@TagAnnotation("database") 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.TYPE}) 
public @interface DatabaseTest { } 

@DatabaseTest 
class MyDatabaseTest1 ... 

@DatabaseTest 
class MyDatabaseTest2 ... 

、その後build.sbtで、並行して実行すること

concurrentRestrictions in Global += exclusiveGroups(Tag("database")) 

ほとんどのテストが、MyDatabaseTest1MyDatabaseTest2を行うだろうもう一方として。

specs2でこれを行うことはできますか?

+0

仕様に同じタグを付けるようにしましたか?私は実際にこれを使って仕様の一致のレベルを下げることができることに気づいていませんでした。 'sequential'引数を使用しない限り、各指定は並行のままです。 – Eric

+0

@Eric、 'TagAnnotation'は、ScalaTestランナーが消費してSBTにさらされている(私が想定している)ScalaTestアノテーションです。私はそれを明確にすべきだった。 –

+0

そして、スペック内のサンプルの実行は、SBTではなくspecs2によって制御されます。 1つのファイルですべての例を見ることができるので、制御が容易であることがわかります。 –

答えて

0

自分で機能を追加しました。 (ビルトインサポートするための問題:https://github.com/etorreborre/specs2/issues/470

SRC /試験/ジャワ/試験/ Tag.scala

最初に使用する注釈を定義します。 (私はこれはJavaでのみ行うことができると信じています。)

package test; 

import java.lang.annotation.*; 

@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.TYPE}) 
public @interface Tag { 
    String name(); 
} 

のsrc /テスト/スカラ座/テスト/ TaggingFramework.scala

その後Frameworkをラップし、タグを追加しsbt.testing.Frameworkの実装を定義します注釈。 (注:これはorg.scala-sbt:test-interfaceに依存すでにspecs2に引いている場合、それはすでにあるはずです。。)

package test 

import java.lang.annotation.Annotation 
import sbt.testing._ 
import scala.util.Try 

class TaggingFramework(framework: Framework) extends Framework { 
    def fingerprints(): Array[Fingerprint] = framework.fingerprints() 

    def name = s"TaggingFramework(${framework.name})" 

    def runner(args: Array[String], remoteArgs: Array[String], testClassLoader: ClassLoader) = { 
    val runner = framework.runner(args, remoteArgs, testClassLoader) 
    println(runner) 
    new Runner { 
     def args() = runner.args() 

     def done() = runner.done() 

     def remoteArgs = runner.remoteArgs() 

     def tasks(taskDefs: Array[TaskDef]) = runner.tasks(taskDefs).map { task => 
     new Task { 
      def execute(eventHandler: EventHandler, loggers: Array[Logger]) = task.execute(eventHandler, loggers) 
      def taskDef = task.taskDef 
      def tags = task.tags ++ { 
      val fingerprint = taskDef.fingerprint 
      Try { 
       val isModule = fingerprint.getClass.getMethod("isModule").invoke(fingerprint).asInstanceOf[Boolean] 
       val className = taskDef.fullyQualifiedName + (if (isModule) "$" else "") 
       println(testClassLoader.loadClass(className).getAnnotationsByType(classOf[Tag]).map(_.name).toSeq) 
       testClassLoader.loadClass(className).getAnnotationsByType(classOf[Tag]).map(_.name) 
      }.getOrElse(Array.empty) 
      } 
     } 
     } 
    } 
    } 
} 

プロジェクト/ TaggingTestFramework.scala

次にビルド定義では、TaggingTestFrameworkを定義しますsbt.TestFrameworkのサブクラスです。存在する場合はTaggingFrameworkがロードされます。それ以外の場合は、元のフレームワークを使用するだけです。

build.sbt

import sbt.TestFramework 
import sbt.testing._ 
import scala.language.existentials 
import scala.util.Try 

class TaggingTestFramework(testFramework: TestFramework) extends TestFramework() { 
    override def create(loader: ClassLoader, log: sbt.Logger) = testFramework.create(loader, log).map { framework => 
    Try(
     Class.forName("test.TaggingFramework", true, loader).asInstanceOf[Class[Framework]] 
     .getConstructor(classOf[Framework]).newInstance(framework) 
    ).getOrElse(framework) 
    } 

    override def toString = s"TaggingTestFramework($testFramework)" 
} 

そしてtestFrameworksを包みます。

testFrameworks := testFrameworks.value.map(new TaggingTestFramework(_)) 

ほとんどの場合、specs2を含む任意のScalaまたはJavaフレームワークで動作します。


SRC /試験/スカラ/例/ MySpec.scala

最後に、単にクラスにアノテーションを追加し、試験タスクにタグを追加使用します。

import org.specs2.mutable.Specification 
import test.Tag 

@Tag(name = "database") 
class MySpec extends Specification ... 

注1:これは、現在の継承では動作しません。

注2:SBT分岐テストは、動作が大きく異なります。これと他の多くのテスト機能は、フォークテストでは使用できません。

+0

これはクールなアイデアです! – Eric

関連する問題