假设我有一个函数runConcurrently(f1: Int => Int, f2: Int => Int): (Int, Int)
,该函数返回f1
和f2
的结果。
现在,我想编写一个测试以确保在调用f1
时f2
和runConcurrently
同时运行 。我想使测试具有确定性并尽可能高效。
您如何建议编写测试?
P.S。我不想将其与任何特定的测试框架或库结合使用。唯一的依赖关系应该是Scala / Java SDK。
答案 0 :(得分:5)
您能做的最接近的事情是使用两个函数都使用的某种共享条件:
def runConcurrently(f1: => Int, f2: => Int): Future[(Int, Int)] =
Future(f1) zip Future(f2)
val sem1 = new Semaphore(0)
val sem2 = new Semaphore(0)
def f1 = {
sem1.release
sem2.acquire
1
}
def f2 = {
sem2.release
sem1.acquire
2
}
Await.result(runConcurrently(f1, f2), 1 second) shouldBe (1,2)
这个想法是,至少在另一个功能启动之前,这两个功能都无法完成。因此,按顺序运行它们的尝试将永远不会完成,并且您将超时。
尤其是,如果您尝试在单线程执行上下文中运行它,则此代码将失败。
答案 1 :(得分:0)
如前所述,这可能不会一直有效,也远不是确定性的。
但是,它可能会为您服务。
final class FunctionMeter[-I, +O](private[this] val underlying: I => O) {
private[this] var start: Long = _
private[this] var finish: Long = _
def getStartTime: Long = start
def getFinishTime: Long = finish
def getFun: I => O = input => {
start = System.nanoTime()
val output = underlying(input)
finish = System.nanoTime()
output
}
}
def test(f1: Int => Int, f2: Int => Int): Boolean {
val m1 = new FunctionMeter(f1)
val m2 = new FunctionMeter(f2)
runConcurrently(m1.getFunction, m2.getFunction)
m2.getStartTime < m1.getFinishTime && m1.getStartTime < m2.getFinishTime
}
无论如何,我和Dima在一起,这不是您应该测试的东西。
答案 2 :(得分:-1)
一个丑陋问题的丑陋解决方案:
object Test extends App {
def runConcurrently(f1: () => Int, f2: () => Int): (Int, Int) = {
import ExecutionContext.Implicits.global
val f = Future(f1())
val g = Future(f2())
Await.result(f.zip(g), Duration.Inf)
}
@volatile var start1: Long = 0
@volatile var start2: Long = 0
@volatile var end1: Long = 0
@volatile var end2: Long = 0
val f1 : () => Int = {
case x : Unit => {
start1 = System.nanoTime()
Thread.sleep(1000)
end1 = System.nanoTime()
1
}
}
val f2 : () => Int = {
case x : Unit => {
start2 = System.nanoTime()
Thread.sleep(1000)
end2 = System.nanoTime()
1
}
}
runConcurrently(f1, f2)
assert(start1 < end2)
assert(start2 < end1)
}