Consider the following Table:
object MyTestsFactory {
val testCases = Table(
("testName", "input", "output"),
("test-1", "1", 1),
("test-2", "2", 2),
("test-3", "3", 3),
)
}
and the following tests case:
class MySpec extends FunSuite {
test("Test Parsing Function") {
forAll(MyTestsFactory.testCases) { (testName: String, input: String, output: Int) =>
input.toInt shouldBe output
}
}
}
Notice that it creates one test, and runs all the inputs on the specific test.
Is that possible to create test for each row on the Table via forAll? is there maybe other solution? (C# solution attached)
For example something as follows:
class MySpec extends FunSuite {
test("Test Parsing Function") {
forAll(MyTestsFactory.testCases) { (testName: String, input: String, output: Int) =>
test(s"Testing $testName") {
input.toInt shouldBe output
}
input.toIntOption match {
case Some(value) => value shouldBe output
case None => fail(s"Parsing error on $testName")
}
}
}
}
which does not compile
TestRegistrationClosedException was thrown during property evaluation. (ConsentStringSpec.scala:12)
Message: A test clause may not appear inside another test clause.
Location: (ConsentStringSpec.scala:13)
Occurred at table row 0 (zero based, not counting headings), which had values (
testName = test-1,
input = 1,
output = 1
)
Is it possible in some way?
Example on C#: (Looking for something similar in Scala)
public class MySpec
{
[TestCase( "1", 1, TestName = "test-1")]
[TestCase("2", 2, TestName = "test-2")]
[TestCase("3", 3, TestName = "test-3")]
public void TestingParsing(string input, int output)
{
Assert.AreEqual(int.Parse(input), output);
}
}
The problem with your code, is that you are trying to nest your tests. It cannot be nested. Please just try to flip the test and forall order, for example:
class MySpec extends FunSuite with Matchers {
forAll(MyTestsFactory.testCases) {
x => {
test("Test Parsing Function" + x._1) {
x._2.toInt shouldBe x._3
}
}
}
}
Then you get 3 tests:
Related
I am trying to implement a test with ScalaTest (WordSpecLike, MustMatchers) that verify if an Either[Seq[Error], Seq[Value]] contains one value and if the value has some specific attributes.
Ideally I would like to have something like:
val result:Either[Seq[Error], Seq[Value]] = ...
result.value must contain { _ have (
'prop ("value")
)}
But this does not compile and I have no clue on how to achieve this kind of matching.
Is there documentation on deep tests or some best practices for that?
Inspectors enable assertions to be made about collections, and in combination with EitherValues, as suggested by #LuisMiguelMejíaSuárez, and checking arbitrary properties with have, the following syntax is possible
atLeast(1, result.right.value) must have ('prop ("value"))
Here is a working example
class Value(val foo: String, val bar: Int) {
def isTooLong: Boolean = foo.length > 2
}
class StackOverflowSpec extends WordSpec with MustMatchers with EitherValues with Inspectors {
"Result" when {
"Right" should {
"have property" in {
val result: Either[Seq[Error], Seq[Value]] = Right(Seq(new Value("aa", 11), new Value("bbb", 42)))
atLeast(1, result.right.value) must have ('tooLong (true), 'bar (42) )
}
}
}
}
Alternatively try pattern matching on result and passing the property predicate to Seq.exists like so
class Value(val foo: String, val bar: String) {
def isTooLong: Boolean = foo.length > 2
}
class StackOverflowSpec extends WordSpec with MustMatchers {
"Result" when {
"Right" should {
"have property" in {
val result: Either[Seq[Error], Seq[Value]] = Right(Seq(new Value("a", "b"), new Value("ccc", "ddd")))
result match {
case Left(seq) => fail
case Right(seq) => seq.exists(_.isTooLong) must be(true)
}
}
}
}
}
{
"cars": [{
"amount": 120.00,
"name": "Car1"
}, {
"amount": 245.00,
"name": "Car2"
}]
}
I am reading above JSON as following in my Controller
val body: JsObject = request.body.asInstanceOf[JsObject]
I am having following CASE CLASS
case class BIC(name: String, amount: Double)
I want to create List[BIC] objects by reading data from JSON [e.g. body] using Functional style
Use Play JSON.
Example:
case class Wrapper(cars: List[Bic])
case class BIC(name: String, amount: Double)
Then in your controller:
implicit val wrapperFormats = Json.format[Wrapper]
implicit val bICFormats = Json.format[BIC]
def postCars(): Action[JsValue] = Action(json.parse) { implicit request =>
request.body.validate[Wrapper] match {
case JsSuccess(obj, _) => {
//do something with obj.
}
case JsError(err) => {
BadRequest(
JsObject(
"error" -> err.toString
)
)
}
}
}
Please note that I am returning Action[JsValue] this is so JQuery will run success when using AJAX.
I hope this helps,
Rhys
another reference:
https://www.playframework.com/documentation/2.5.x/ScalaJsonCombinators
First, define two case classes for your model like this :
object Models {
case class Bic(name : String, amount : Double)
object Bic {
implicit val BicFormat = Json.format[Bic]
}
case class Cars(bics : List[Bic])
object Cars {
implicit val CarsFormat = Json.format[Cars]
}
}
You're using the Play Framework so you can use the JSON library.
In your controller, if you want to read the bics, you can do it like that :
def getCars = Action(parse.json) { request =>
request.body.validate[Cars] map { cars =>
// treat your cars ..
}
}
First off, I saw it and this other post sounds exactly like what I need except for one thing, I can't use fixture.TestDataFixture because I can't extend fixture.FreeSpecLike, and I am sure that there must be some way to get the test name in a way that looks more like this (imagined code that doesn't compile)
class MySpec extends FlatSpecLike with fixture.TestDataFixture {
"this technique" - {
"should work" in {
assert(testData.name == "this technique should work")
}
"should be easy" in { td =>
assert(testData.name == "this technique should be easy")
}
}
}
Any ideas? I just can't believe something like this is not possible :D
While you already came to basically this solution, here is a safer variation:
private val _currentTestName = new ThreadLocal[String]
override def withFixture(test: NoArgTest) = {
_currentTestName.set(test.name)
val outcome = super.withFixture(test)
_currentTestName.set(null)
outcome
}
protected def currentTestName: String = {
val testName = _currentTestName.get()
assert(testName != null, "currentTestName should only be called in a test")
testName
}
Alternately,
protected def currentTestName = Option(_currentTestName.get())
You can find sequence of test names using method testNames in FlatSpecLike trait:
import org.scalatest.FlatSpecLike
class FooSpec extends FlatSpecLike {
it should "check case one" in {
println("test some code ...")
println(testNames.mkString("\n"))
/*
prints:
should check case one
should check case two
*/
// ...
assert(1 == 1)
println("end.")
}
it should "check case two" in {
println("test some code ...")
assert(1 == 1)
println("end.")
}
}
and find each you needed. Hope it helps.
And found an answer(well a collegue did), not sure I like it but works:
on the trait that other tests depend on
class MySpec extends FlatSpecLike {
//... other stuff
var testName = "UndefinedTestName"
override def withFixture (test: NoArgTest) :Outcome= {
testName = test.name
super.withFixture(test)
}
}
simple solution but rather obscure, also I wonder if anyone sees any problems with it
I overloaded a case class's equality operator:
case class Polygon(points: Seq[(Double, Double)]) extends Shape {
def ==(that: Polygon): Boolean = { ... }
}
My unit tests pass when using double-equals in assertions:
import org.scalatest.FunSpec
class ShapeSpec extends FunSpec {
describe("Polygon") {
it("is equal to all its rotations") {
val p = Polygon(Seq( ... ))
for { i ← 0 until p.points.size } {
val q = Polygon(p.points.drop(i) ++ p.points.take(i))
assert(p == q)
}
}
}
}
But when using === instead of ==, the same tests fail:
[info] Polygon
[info] - is equal to all its rotations *** FAILED ***
[info] Polygon(List((-1.0,-1.0), (4.0,-1.0), (4.0,2.0), (1.0,2.0),
(1.0,1.0), (-1.0,1.0))) did not equal PolygonM(List((4.0,-1.0),
(4.0,2.0), (1.0,2.0), (1.0,1.0), (-1.0,1.0), (-1.0,-1.0)))
(ShapeSpec.scala:28)
Why does this happen?
You spelled it wrong. ;)
It should be:
override def equals(x: Any): Boolean
Given a mock:
val myMock = mock[SomeClass]
I am trying to set it up so that the mock returns default values for various types. E.g. for things that returns String, it would return "".
I discovered RETURNS_SMART_NULLS which looks like it works for basic return types like String. Here is how I am using it in Scala / Specs2:
val myMock = mock[SomeClass].settings(smart = true)
Now to the problem: since I am using Scala, my code / APIs do not return nulls but return Option values. So what I am trying to do is get the mock to default to returning a non null value for Option return types: either None (preferred), or Some[T] where T is the type in the container (if its String, then Some("")).
So for example if SomeClass has an attribute address of type Option[String], how can I configure mockito to return None when myMock.address invoked instead of null. These nulls are causing downstream errors.
Note, its not a viable solution for me to specifically mock the behavior of each of these individual invocations (e.g: myMock.address returns None)
I was able to test this class:
class Timers(i: Int, s: String) {
def returnOption: Option[Int] = Some(i)
def returnString: String = s
}
with this test:
import org.specs2.mutable.Specification
import org.junit.runner.RunWith
import org.specs2.runner.JUnitRunner
import org.mockito.Mockito._
import org.mockito.stubbing.Answer
import org.mockito.invocation.InvocationOnMock
#RunWith(classOf[JUnitRunner])
class TimersSpec extends Specification {
val m = mock(classOf[Timers], new Answer[Any]() {
def answer(inv: InvocationOnMock) = {
inv.getMethod.getReturnType match {
case c if c == classOf[Option[_]] => None
case c if c == classOf[String] => ""
case _ => null
}
}
})
"A mock timer" should {
"return a None" in {
m.returnOption must beNone
}
"return a empty string" in {
m.returnString mustEqual ""
}
}
}