Create parameterized test fixtures that depend on other parameterized test fixtures? - pytest

I want to do something like this
def foo_bar(a, b):
""" The function I want to test """
return ...
def subparams(a):
return [some stuff based on what a is]
#pytest.fixture(scope='module', params=('foo', 'bar'))
def a(request):
# lengthy setup based on request.param
yield request.param
# teardown
#pytest.fixture(params=subparams(a))
def b(request):
return request.param
def test_foo_bar(a, b):
result = foo_bar(a, b)
assert <something about result>
In other words, I have a parameterized fixture a which simply takse
a normal list of parameters. For each value of a, I also have a function
subparams for generating associated parameters b. For the sake of argument, let's say that subparams is trivially implemented as follows
def subparams(a):
return [1, 2, 3] if a == 'foo' else [4, 5]
in which case I would want test_foo_bar to be invoked with the following:
'foo', 1
'foo', 2
'foo', 3
'bar', 4
'bar', 5
Unfortunately, the #pytest.fixture(params=subparams(a)) bit doesn't work because at that point a is still just a function, not an instantiation based on a's parameterization. How do I achieve the effect of having test_foo_bar called with those kinds of combinations of a and b where a takes a long time to set up (hence the scope='module' bit) and b is parameterized depending on a?

Related

pytest use data from one test as parameter to another test

I am wondering if it is possible to use data generated from one test as parameter to another test. In my case I need to modify variable (this is list) and it will be great if I can use this list as param (run as many tests as list have)
Here is code (it is not working, but maybe You can give me some hints)
import pytest
class TestCheck:
x = [1, 4]
#classmethod
def setup_class(self):
print('here setup')
#classmethod
def teardown_class(self):
print('here is finish')
def test_5(self):
self.x.append(6)
assert 1 == 2
#pytest.mark.parametrize("region", x)
def test_6(self, region):
assert region > 5, f"x: {self.x}"
Output:
FAILED sandbox_tests3.py::TestCheck::test_5 - assert 1 == 2
FAILED sandbox_tests3.py::TestCheck::test_6[1] - AssertionError: x: [1, 4, 6]
FAILED sandbox_tests3.py::TestCheck::test_6[4] - AssertionError: x: [1, 4, 6]
So it looks that in x there is good values, however in fixture new values are not visible.
I was also trying to use pytest_cases, but results are very similar.
Any help is appreciate

Testing a generated curried function with Scala Test

I'm having hard times trying to create a Scala Test to checks this function:
def curry[A,B,C](f: (A,B) => C): A => (B => C) =
a => b => f(a,b)
The first thought I had was to validate if given a function fx passed into curry(fx) function, will return a curried version of it.
Any tips?
One way to test it, is to pass different f's to it and see if you are getting back the function you expect. For example, you can test an f that returns the arguments as a tuple:
def f(x: String, y: Int) = (x, y)
curry(f)("4")(7) must be(("4", 7))
IMO, testing it for a few different functions f and for a few different a and b would be more than sufficiently assuring that something as trivial as this works as intended.

Difference between f(a,b) and f(a)(b) in Scala

I am very very new to Scala. I am reading a book called functional programming in scala by Paul Chiusano and Rúnar Bjarnason. So far I am finding it interesting. I see a solution for curry and uncurry
def curry[A,B,C](f: (A, B) => C): A => (B => C)= {
a => b => f(a,b)
}
def uncurry[A,B,C](f: A => B => C): (A, B) => C = {
(a,b) => f(a)(b)
}
In Curry I understand f(a,b) which results in value of type C but in uncurry I do not understand f(a)(b). Can anyone please tell me how to read f(a)(b) or how is this resulting to a type of C or please refer me some online material that can explain this to me?
Thanks for your help.
Basically the return type of f(a) is a function of type B => C lets call this result g.
If you then call g(b) you obtain a value of type C.
f(a)(b) can be expanded to f.apply(a).apply(b)
In the uncurry method you take a so-called "curried" function, meaning that instead of having a function that evaluates n arguments, you have n functions evaluating one argument, each returning a new function until you evaluate the final one.
Currying without a specific support from the language mean you have to do something like this:
// curriedSum is a function that takes an integer,
// which returns a function that takes an integer
// and returns the sum of the two
def curriedSum(a: Int): Int => Int =
b => a + b
Scala however provides further support for currying, allowing you to write this:
def curriedSum(a: Int)(b: Int): Int = a + b
In both cases, you can partially apply curriedSum, getting a function that takes an integer and sums it to the number you passed in originally, like this:
val sumTwo: Int => Int = curriedSum(2)
val four = sumTwo(2) // four equals 4
Let's go back to your case: as we mentioned, uncurry takes a curried function and turns it into a regular function, meaning that
f(a)(b)
can read as: "apply parameter a to the function f, then take the resulting function and apply the parameter b to it".
In case if somebody is looking for an explanation. This link explains it better
def add(x:Int, y:Int) = x + y
add(1, 2) // 3
add(7, 3) // 10
After currying
def add(x:Int) = (y:Int) => x + y
add(1)(2) // 3
add(7)(3) // 10
In the first sample, the add method takes two parameters and returns the result of adding the two. The second sample redefines the add method so that it takes only a single Int as a parameter and returns a functional (closure) as a result. Our driver code then calls this functional, passing the second “parameter”. This functional computes the value and returns the final result.

Can someone explain the scala code below?

scala> def lift3[A,B,C,D] (
| f: Function3[A,B,C,D]): Function3[Option[A], Option[B], Option[C], Option
[D]] = {
| (oa: Option[A], ob:Option[B], oc: Option[C]) =>
| for(a <- oa; b <- ob; c <- oc) yield f(a,b,c)
| }
lift3: [A, B, C, D](f: (A, B, C) => D)(Option[A], Option[B], Option[C]) => Option[D]
In particular, the following line:
def lift3[A,B,C,D] (
f: Function3[A,B,C,D]): Function3[Option[A], Option[B], Option[C], Option
[D]]
This is taken from the book Scala In Depth by Joshua D Suereth (Listing 2.1, chapter 2). I'm not sure what purpose the additional Option[D] serves. In the body of the function, the code only maps to the first three parameters to the output type D. When then, D is declared in the input parameter list? Am I missing something?
With my limited understanding, I would read the function declaration as a function that takes a function as a parameter (which in turn takes 4 parameters) and returns a function that takes 4 parameters. Also, why is there no mention of the return type?
Thanks in advance!
With my limited understanding, I would read the function declaration as a function that takes a function as a parameter (which in turn takes 4 parameters) and returns a function that takes 4 parameters. Also, why is there no mention of the return type?
Function3[A,B,C,D] is a function with 3 parameters (of types A, B and C) and D is the return type (it can also be written as (A, B, C) => D; this is exactly the same type). So in Function3[Option[A], Option[B], Option[C], Option[D]], Option[D] is the return type, not a parameter type.
A function3 takes 3 parameters. The D is the return type of the function. What the code does, is take a function with 3 arguments and return a function with 3 arguments, where each argument and its return type is "lifted" to an Option.
You can check out the API docs for Function3 here.
And an explanation for the R generic type can be found in the docs for Function2

Scala iterate over a set of objects

I have a sealed trait which is implemented by 3 objects
sealed trait MyTrait {
...
}
object A extends MyTrait { ... }
object B extends MyTrait { ... }
object C extends MyTrait { ... }
I'm using Scalaz's validation mechanism wherein the apply methods of the objects A, B and C return a validated type. the Objects A, B and C does contain some logic and I want to apply this logic sequentially, i.e., I want to first apply A and check what the result of A is and based on it, decide if I want to call B or just return the validated result. I want to repeat this until I hit C after which I just return whatever I get as a result of calling C.
Currently I have a static approach where I first call A, pass the result of A to a utility method and check for the result and then call B.
def apply(request: Request): Validated[Result] = {
val vResultA = run(request, A)
val vResultB = if (isResultOk(vResultA)) run(request, B) else vResultA
if (isResultOk(vResultB)) run(request, C) else vResultB
}
Is there a better way to do this? Any suggestions or any patterns that I can apply?
We will define succeeded results = results that are OK, and failed results = results that are not OK.
First, A, B, and C are all objects extending MyTrait. Therefore, they can be grouped into an Array or a List of MyTrait.
val objects = Array(A, B, C) /* You can use List instead if you want. */
Then the type of objects is Array[MyTrait].
Next, we have to iterate on this Array.
However, just calling map on this Array continues mapping even if the previous isResultOk() is false.
Therefore, we will use Stream instead of Array.
Let's see how using Stream can stop calling map if some condition is satisfied.
Array(1, 2, 3, 4, 5).map(i => {
println(i)
i + 100
}).takeWhile(_ <= 103).foreach(println(_))
The output of the above code will be:
1
2
3
4
5
101
102
103
So, map() ends, and then takeWhile() ends -- takeWhile() does not affect calling map().
However, if we do the same operations on the Stream,
Array(1, 2, 3, 4, 5).toStream.map(i => {
println(i)
i + 100
}).takeWhile(_ <= 103).foreach(println(_))
The output will be:
1
101
2
102
3
103
4
So the calling will be map() -> takeWhile() -> foreach() -> map() -> takeWhile() -> ...
At the end, 4 is printed, and 4 + 100 = 104 > 103 will be cut in takeWhile().
The following elements will be not accessed further.
So, do we have to use takeWhile?
objects.toStream.map(run(request, _)).takeWhile(isResultOk(_))
This will get rid of failed results, even though we need the first failed result if failure occured.
(i.e. This will make a problem if there is any result that is not OK.)
How about the opposite function dropWhile()?
objects.toStream.map(run(request, _)).dropWhile(isResultOk(_))
This will get rid of all succeeded results, even though all results are succeeded.
(i.e. This will make a problem if all results are OK.)
So, we will use span().
c.span(p) = (c.takeWhile(p), c.dropWhile(p))
We will test if there are results that are not OK.
If there is a result that is not OK, then we will return the first such result.
Otherwise, we will return the last result that is OK.
val (succ, fail) = objects.toStream.map(run(request, _)).span(isResultOk(_))
fail.headOption.getOrElse(succ.last)
fail.headOption will return Some(fail's first element) if fail is not empty, otherwise None.
In summary,
val objects = Array(A, B, C)
def apply(request: Request): Validated[Result] = {
val (succ, fail) = objects.toStream.map(run(request, _)).span(isResultOk(_))
fail.headOption.getOrElse(succ.last)
}