pytest mock patch side_effect not iterate when used together with pytest.mark.parametrize - pytest

I have the below pytest script and the side_effect value [2, 6] is not getting iterated. It is always stuck with value 2 in the test function test_my_function.
My question is:
How to make the side_effect value iterate together with parametrize test cases in function test_my_function. (assume we must use parametrize).
#!/usr/bin/env python3
#
import pytest
def my_function(x):
return x*2
#pytest.fixture
def mock_my_function(mocker):
mocker.patch(
__name__ + ".my_function", side_effect=[2, 6]
)
#pytest.mark.parametrize("input, expect", [(1, 2), (3, 6)])
def test_my_function(input, expect, mock_my_function):
assert expect == my_function(input)

first, your test isn't really testing anything if you mock the function you're trying to test
second, function-scoped fixtures are set up each time the test function is called -- for each parametrization case-set it'll run your fixture
this means (in your example) that both invocations of your test will have my_function mocked to return 2 for the only call that happens
if you want to additionally parametrize the mocked function, I would suggest including it in your parametrize list:
#pytest.mark.parametrize(
('input', 'expect', 'mocked_ret'),
(
(1, 2, 2),
(3, 6, 6),
),
)
def test_my_function(input, expect, mocked_ret, mocker):
mocker.patch(f"{__name__}.my_function", return_value=mocked_ret)
assert my_function(input) == expect
disclaimer: I'm a pytest core dev

Related

How to assert setup outside teardown in multiply tests

I have a lot of tests, and every test assert something specific, but also assert the setup was done as expected. The setup cannot be verified before the tests starts.
My approach is to assert in the tear-down. Is there a better approach where I do not have to add the assert to every test file, since I have hundredths of them.
Minimal example:
my_test.py
import pytest
#pytest.mark.parametrize("number_a", [1, 2, 3, 4, 5, 6, 7])
def test_low_numbers(number_a):
run_test(number_a=number_a)
def run_test(number_a):
assert number_a != 4
conftest.py
def very_important_check(number_a):
assert number_a != 2, "Not two, stupid."
#pytest.fixture(autouse=True, scope="function")
def signal_handler(request, number_a):
print("########Setup")
yield
print("########Teardown")
very_important_check(number_a)

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

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

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?

Performance difference between def and val

Consider the below code where I am passing a method and a function as a parameter to map()
val list1:List[Int]=List(10,20,30)
def func1(x:Int):Int={
x+10
}
list1.map(func1)
list1.map(_+10)
I have few questions about ETA expansion:
Is there a performance difference in using a method in place of a function, especially since the method is internally getting converted into a function?
Is there a performance difference between def x:Int=10 and val x:Int=10?
I have read that the call-by-name parameter is actually a method which does not accept any parameter. Now, if methods are not objects, how are we using a method as a parameter value?
There is no significant difference between the expressions you're asking about.
val x incurs a private field.
Note that vs.map(_+10) inlines the function, as compared to vs.map(x => f(x)). But you have to create a function object in any case.
A call-by-name argument => X is a () => X under the hood.
From the REPL, use javap to show code. -c for code, -v for verbose.
scala> vs.map(f)
res0: List[Int] = List(2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
scala> :javap -pv -
[snip]
One of the differences is, val values are measured when class is loaded whilst def are measured when called.
A simple example is, say you have 100K val variables in the class (for argument's sake), the system might take long time to start. But if you have a def A in which declares 100K val. The performance will be hit only when the A is called.

Scalatest Matcher - Check single value exists in a set of values

I am generating a value, and I know the possible values it could be. I want to write this
val myInt = someFunction()
myInt shouldBe oneOf (1, 2, 3)
However this doesn't seem to work for me as of Scalatest 3 M15. My workaround is
List(myValue) should contain atMostOneOf (1, 2, 3)
Which is a lot more confusing to read and understand.
Is there a way to do what I want here? It seems like a common scenario.
oneOf can only be used to compare contents of collections. You can use Some as a simple one-element collection:
Some(myInt) should contain oneOf (1, 2, 3)
Alternatively:
myInt should (equal(1) or equal(2) or equal(3))