1

I have a unit test, which test some solution. But this test code can also be applied for testing the other, very similar solution. What I want to make is code of test be generic to be applied to both solutions, like this:

describe("when table contains all correct rows") {
      it("should be empty") {
        def check[T](func: T => List[Row]) = {
          val tableGen = new TableGenerator()
          val table: Vector[Row] = tableGen.randomTable(100)
            .sortWith(_.time isBefore _.time).distinct
          val result: List[Row] = func(table)
          assert(result.isEmpty)
        }

        check(Solution.solution1)
        check(Solution.solution2)
      }
    }

where solutions have types:

solution1: IndexedSeq[Row] => List[Row]
solution2: Seq[Row] => List[Row]

how check() function has to be written to be able to do that? And what's the best approaches to write this (might be in other way) with eliminated code duplication?

Update: When I try to compile this code I get type mismatch error in func(table):

Error:(36, 29) type mismatch;
 found   : table.type (with underlying type scala.collection.immutable.Vector[com.vmalov.tinkoff.Row])
 required: T
          val result = func(table)
5
  • Why do you think you need to do anything? This check function should already be able do that, and there is no duplicate code to be eliminated in what you've shown. Commented Sep 30, 2016 at 14:17
  • Once I'm trying to compile I get type mismatch error: found Vector[Row], required T (table I pass to func). The second question was about may be there is another, better/prefferable way to abstract such things. Commented Sep 30, 2016 at 14:20
  • You should add that in the question. Commented Sep 30, 2016 at 14:20
  • Ok, sorry, missed a bit. Commented Sep 30, 2016 at 14:22
  • I recommend you add a message with something to help identify the test, otherwise if a test fails, you won't know quickly which of the two did. Commented Sep 30, 2016 at 14:26

2 Answers 2

4

For this to work, you need to be able to pass a Vector[Row] to func, so any Vector[Row] has to be a T; that is, T is a supertype of Vector[Row]. You can tell this to the compiler by using a type parameter bound:

def check[T >: Vector[Row]](func: T => List[Row])

Alternately, by the above reasoning, a function T => List[Row] will also be a function Vector[Row] => List[Row] precisely when T is a supertype of Vector[Row], and the Scala compiler knows about this (functions are contravariant in their argument type(s)). So this signature is equivalent to simpler

def check(func: Vector[Row] => List[Row])

Of course, you can generalize this, but how much depends on your specific desires. E.g. you can replace List[Row] with Seq[Row] (everywhere), or with a type parameter and pass an extra function to check:

def check[A](func: Vector[Row] => A)(test: A => Boolean) = {
  val table = ...
  val result = func(table)
  assert(test(result))
}

check(Solution.solution1)(_.isEmpty) // the compiler infers A is List[Row] 
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much! This is exactly what I wanted.
3

Your case, maybe is enough to abstract the type on a more specific way, like defining that you are expecting a Travesable.

  def check[S[_] : Traversable](func: S[Row] => List[Row])

That would accept either Seq or IndexedSeq as valid parameter, while it also be limiting it.

I hope it helps

EDITED: Check Alexey Romanov Answer, as with this you will not be able to call func the way you do it. Sorry about that

def check(func: Vector[Row] => List[Row])

3 Comments

I think you mean S[X] <: Traversable[X].
This doesn't seem to solve the issue, I was too quickly answering :P but Alexey Romanov seems to have answered this one pretty well.
Thanks for response. But indeed, this doesn't solve the problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.