4

I’m using Project Euler to learn functional programming in Scala, along with sbt and other best practices. My initial stab at creating tests to verify solutions using ScalaTest was:

package euler
import org.scalatest._

class SolutionsSpec extends Spec with Matchers {
    "The problems" should "have the correct solutions" in {
        Problem1.solve should be (  233168 )
        Problem2.solve should be ( 4613732 )
        Problem3.solve should be (    6857 )
        Problem4.solve should be (  906609 )
    }
}

This is concise, but I’m afraid it might not scale if I ever get to harder problems with longer run times. As far as I can tell, I can't test individual problems this way.

I have searched on GitHub and found two helpful examples, similar to what I am trying to do:

Both are more verbose than I would like, since I’m basically just testing a mapping from problem number to solutions.

My question: Is there a concise and elegant way to do this testing that is still flexible so that I can check the result for a single or group of problems?

Edit: I found this answer discouraging TDD with Project Euler. To clarify, I am writing unit tests for math helper functions as well. My purpose for checking the answers is partly to check for regressions, but most important as an exercise.

Edit 2: I am now trying to use FunSuite:

class SolutionsSuite extends FunSuite with Matchers {
    test("Problem 1") { Problem1.solve should be (  233168 ) }
    test("Problem 2") { Problem2.solve should be ( 4613732 ) }
    test("Problem 3") { Problem3.solve should be (    6857 ) }
    test("Problem 4") { Problem4.solve should be (  906609 ) }
}

This might be closer to what I want. The output looks better:

$ sbt test
...
[info] SolutionsSuite:
[info] - Problem 1 (28 milliseconds)
[info] - Problem 2 (4 milliseconds)
[info] - Problem 3 (38 milliseconds)
[info] - Problem 4 (172 milliseconds)

But I have still not been able to figure out how to run a subset of the problems. This question seems to indicate that what I am looking for is not yet possible with sbt: Run just a specific scalatest test from sbt.

Edit 3: It looks like the ability to run single test function as opposed to an entire suite is targeted for sbt 0.13.3 per issue Allow running of single junit test #911.

Edit 4: For reference, my Project Euler GitHub project.

Community
  • 1
  • 1
Erik J. Sturcke
  • 158
  • 2
  • 5

1 Answers1

2

You might like to copy my setup at https://github.com/sethtisue/project-euler . Each test looks like:

class Problem1 extends Problem(1, "12345") {
  def solve: Int = ...
}

Where the "12345" is the expected answer (always a string), and the return type of solve can be anything (since it's just going to get .toStringed, since a string is what you're going to end up entering at the Euler site).

Problem is defined such that each problem is its own suite, so you can easily use sbt's test-only command to run just the problems you want.

Seth Tisue
  • 28,052
  • 11
  • 78
  • 142
  • Interesting to think of the problem solvers as tests rather than putting them in `main`. That way you can encapsulate each solution, but don’t need excessive duplicate code just to check the answers. Also, thanks for the tip of using parameters with the `Problem` trait. – Erik J. Sturcke Mar 13 '14 at 14:03