ScalaTest:是否存在将测试套件定义为对象而非类的缺陷?

时间:2016-09-13 10:16:30

标签: scala scalatest

我有一个非常具体的用例,为了减少测试套件的实例化时间,我将它们定义为一个对象,而不是一个类,例如。

#server.R
library(shiny)
function(input, output) {

  uploaded_data <- reactive({
    inFile <- input$file1
    read.table(inFile$datapath, header=input$header, sep=input$sep, quote=input$quote)
  })

  react_vals <- reactiveValues(data = NULL)

  output$choose_columns <- renderUI({
    req(input$file1)

    colnames <- names(uploaded_data())
    checkboxGroupInput("choose_columns", "Choose columns", 
                       choices  = colnames,
                       selected = colnames)
  })

  output$choose_column <- renderUI({
    req(input$file1)
    is_factor <- sapply(uploaded_data(), is.factor)
    colnames <- colnames(uploaded_data()[is_factor])
    selectInput("choose_column", "Choose column", choices = colnames)
  })

  observeEvent(input$file1, react_vals$data <- uploaded_data())
  observeEvent(input$choose_columns, react_vals$data <- uploaded_data()[, input$choose_columns])

  observeEvent(input$filter, {
    react_vals$data <-
      #Option A
      eval(parse(text = sprintf("subset(uploaded_data(), %s != '%s')", input$choose_column, input$column_value)))

      #Option B
      #subset(uploaded_data(), uploaded_data()[, which(names(uploaded_data()) == input$choose_column)] != input$column_value)
  })

  output$contents <- renderTable(react_vals$data)
}

shinyApp(ui, server)

这有效,但这样做是否存在根本问题或缺陷?如果每个测试都是单独执行的,并且在套件级别具有可修改状态的不幸情况下,则应与多线程问题分开。

更新:当我说“减少实例化时间”时,我的意思是整体在对象/类中计算重量级夹具数据而不仅仅是纯粹的套件类实例化时间。由于object是一个单例,因此它将是一个查找而不是一个新类的实例化。

我需要这样做才能在计算机网格中分发数百万个测试。有些测试是标准的scalatest,其他测试正在评估一组输入参数的排列,因此需要减少套件实例化的启动时间。

btw我这样做是为了在集群机器中执行每个测试:

import org.scalatest._
import scala.collection.mutable.Stack

object StackSuite extends FunSuite with Matchers {
    test("stackShouldPopValuesIinLastInFirstOutOrder") {
        val stack = new Stack[Int]
        stack.push(1)
        stack.push(2)
        stack.pop() should equal(2)
        stack.pop() should equal(1)
     }
}

2 个答案:

答案 0 :(得分:2)

  

为了减少测试套件的实例化时间,我将它们定义为一个对象,而不是一个类

我快速了解了org.scalatest.tools.Runner(以及DiscoverySuite)的实施情况,我认为这不会减少实例化时间。

请记住how objects are actually compiled on JVM:您有一个class StackSuite$扩展Suite并且有一个公共无参数构造函数(因为它必须从StackSuite静态调用初始化)。它的发现和处理方式与class StackSuite完全相同。

编辑:如果您找到套件并以这种方式自己运行而不是使用ScalaTest自己的API,那么是的,您将获得查找而不是实例化。假设没有并发问题,应该没有问题:execute本身就是线程安全的。

答案 1 :(得分:1)

如果您觉得不需要使用继承来模块化测试,那么使用Object而不是类就没有问题。其他课程可以帮助您分离不同类型的测试。

来自ScalaTest docs

  

我们建议您为项目创建抽象基类,将最常用的功能混合在一起,而不是通过重复混合相同的特征来复制代码。例如,您可以为单元测试创​​建一个UnitSpec类(不是trait,用于更快速的编译),如下所示:

package com.mycompany.myproject

import org.scalatest._

abstract class UnitSpec extends FlatSpec with Matchers with
OptionValues with Inside with Inspectors
  

然后,您可以使用自定义基类为项目编写单元测试,如下所示:

package com.mycompany.myproject

import org.scalatest._

class MySpec extends UnitSpec {
  // Your tests here
}