How to set a list of pytest markers to a test? - pytest

I am using 2 markers '#pytest.mark.regression' and '#pytest.mark.smoke'. I need all my tests to have these 2 markers, so I wanted to create a list like
allmarkersList = [pytest.mark.regression, pytest.mark.smoke] and I want to call this marker #allmarkersList to all my tests, is this possible ?
import pytest
allmarkers = [pytest.mark.regression, pytest.mark.smoke]
#pytest.mark.regression
def test_reg1():
assert True
#pytest.mark.regression
def test_reg2():
assert True
#pytest.mark.smoke
def test_smoke1():
assert True
#pytest.mark.smoke
def test_smoke2():
assert True
#allmarkers
def test_reg_and_smoke():
print(all_marks)
assert True
when I run this I get the below error -
#allmarkers
E TypeError: 'list' object is not callable

Related

How to use multiple pytest fixtures with same parameterized input to test methods in a class

I want to achieve something like this:
my conftest.py will contain:
fixture_1 - will do some manipulation with input such as a, b, c using request.param
fixture_2 - will do some manipulation with input such as a, b, c using request.param
fixture_3 - will do some manipulation with input such as a, b, c using request.param
#pytest.mark.parametrize('param_name', ['a', 'b', 'c'], indirect=True)
class TestDummy(object):
def test_x(self, fixture_1):
fixture_1_output = fixture_1
assert False
def test_y(self, fixture_2):
fixture_2_output = fixture_2
assert False
def test_z(self, fixture_3):
fixture_3_output = fixture_3
assert False
Any suggestion would be highly appreciated.
You cannot directly patameterize the fixture name this way. Either you use parametrize for each test separately:
def params():
return ['a', 'b', 'c']
class TestDummy:
#pytest.parametrize(fixture_1, params, indirect=True)
def test_x(self, fixture_1):
fixture_1_output = fixture_1
assert False
#pytest.parametrize(fixture_2, params, indirect=True)
def test_y(self, fixture_2):
fixture_2_output = fixture_2
assert False
#pytest.parametrize(fixture_3, params, indirect=True)
def test_z(self, fixture_3):
fixture_3_output = fixture_3
assert False
(I moved the parameters into an extra function for convenience)
Or you have to do the parametrization dynamically based on the fixture name using pytest_generate_tests:
def pytest_generate_tests(metafunc):
fixtures = [f for f in metafunc.fixturenames if f.startswith("fixture_")]
if len(fixtures) == 1:
metafunc.parametrize(fixtures[0], ['a', 'b', 'c'], indirect=True)
class TestDummy:
def test_x(self, fixture_1):
fixture_1_output = fixture_1
assert False
def test_y(self, fixture_2):
fixture_2_output = fixture_2
assert False
def test_z(self, fixture_3):
fixture_3_output = fixture_3
assert False
def test_something_else(self):
pass
You need to determine which tests to parametrize - in this example all tests are parametrized which have exactly one fixture with a name starting with "fixture_", you may have to adapt ths to your needs.
In this example, the first 3 tests will be parametrized, but not the last one (test_something_else).

How can I recur a Zio schedule until a particular value is produced?

Suppose I have an IO (therefore unsafe) operation that will either return true or false. I want to use the Zio scheduling mechanism to execute this until the value is true, but only up to a maximum of N times. To adopt the code from the documentation and change it to what I'm trying to achieve...
import zio._
import zio.duration._
import zio.console._
import zio.clock._
import java.util.Random
object API {
// our API method will return true about 30% of the time, but
// return false the rest of the time (instead of throwing an
// exception, as is shown in documentation)
def makeRequest: Task[Boolean] = Task.effect {
new Random().nextInt(10) > 7
}
}
object ScheduleUtil {
def schedule[A] = Schedule.spaced(1.second) && Schedule.recurs(4).onDecision({
case Decision.Done(_) => putStrLn(s"done trying")
case Decision.Continue(attempt, _, _) => putStrLn(s"attempt #$attempt")
})
}
import ScheduleUtil._
import API._
object ScheduleApp extends scala.App {
implicit val rt: Runtime[Clock with Console] = Runtime.default
rt.unsafeRun(makeRequest.retry(schedule).foldM(
ex => putStrLn("Exception Failed"),
v => putStrLn(s"Succeeded with $v"))
)
}
// run the app
ScheduleApp.main(Array())
This doesn't work, of course. The output is either Succeeded with false or (occasionally) Succeeded with true. I tried adding Schedule.recurUntilEquals to the Schedule definition, but to no avail.
object ScheduleUtil {
def schedule[A] = Schedule.spaced(1.second) && Schedule.recurUntilEquals(true) && Schedule.recurs(4).onDecision({
case Decision.Done(_) => putStrLn(s"done trying")
case Decision.Continue(attempt, _, _) => putStrLn(s"attempt #$attempt")
})
}
import ScheduleUtil._
// re-define ScheduleApp in the exact same way as above, and the following error results:
cmd93.sc:5: polymorphic expression cannot be instantiated to expected type;
found : [A]zio.Schedule[zio.console.Console,Boolean,((Long, Boolean), Long)]
(which expands to) [A]zio.Schedule[zio.Has[zio.console.Console.Service],Boolean,((Long, Boolean), Long)]
required: zio.Schedule[?,Throwable,?]
rt.unsafeRun(makeRequest.retry(schedule).foldM(
How can I accomplish such a use case using the Zio scheduler? Of course, I can redefine the makeRequest task to deliberately throw an exception, instead of returning false, and this works just as in the documentation. But I was hoping to avoid unnecessary exception generation/handling.
object API {
// our API method will return true about 30% of the time, but
// return false the rest of the time (instead of throwing an
// exception, as is shown in documentation)
def makeRequest = Task.effect {
if (new Random().nextInt(10) > 7) true else throw new Exception("Not true")
}
}
Your issue is that the you are using retry on the effect instead of repeat which is what you want since you will be explicitly bypassing the error channel as you mentioned.
So simply change makeRequest.retry(schedule) to makeRequest.repeat(schedule) and it should work.
For a more detailed description consider the signatures below:
// Schedule.spaced
def spaced(duration: Duration): Schedule[Any, Any, Long]
// Schedule.recurs
def recurs(n: Int): Schedule[Any, Any, Long]
// Schedule.recurUntilEquals
def recurUntilEquals[A](a: => A): Schedule[Any, A, A]
Schedule has three type parameters, -Env, -In, +Out, the Env is the same as the standard R type that is part of ZIO, but In and Out are different from the standard E and A on the other ZIO types. This is because the Schedule describes "recurring schedule, which consumes values of type In, and which returns values of type Out" according to the docs. For spaced and recurs the input is Any indicating that it will accept any input value and by extension also doesn't constrain the value. You can see this by composing the two together:
val s: Schedule[Any, Any, (Long, Long)] = Schedule.spaced(1.second) && Schedule.recurs(1)
This is also why it doesn't cause any compiler errors when used as part of retry, because they don't have any specific requirements on the error channel when they don't make use of it. But this also hides your problem because retry only uses the schedule if there is an error but since you were returning true or false you didn't end up receiving an error and your schedule was never invoked.
Once you added the recurUntilEquals an input constraint is added to the schedule:
val s: Schedule[Any, Boolean, ((Long, Long), Boolean)] = Schedule.spaced(1.second) && Schedule.recurs(1) && Schedule.recurUntilEquals(true)
Now you are saying that the input that should be fed into the Schedule is actually a boolean, but retry has the signature:
def retry[R1 <: R, S](policy: Schedule[R1, E, S])(implicit ev: CanFail[E]): ZIO[R1 with Clock, E, A]
Notice that the second position of the Schedule in the policy argument is the E parameter which is the error type and since Throwable =!= Boolean you get a compiler error as a result.
Correspondingly this is the signature for repeat
def repeat[R1 <: R, B](schedule: Schedule[R1, A, B]): ZIO[R1 with Clock, E, B]
Here we see that the schedule actually takes the A type which in this case would be the response from your API or Boolean which matches with what you are expecting in your provided schedule.
I'm using ZIO.repeatWhile(task)(condition) which works pretty well for my case.

Spark/Scala - Failed to execute user defined function

I have the following code that works.
val locList = Source.fromInputStream(getClass.getResourceAsStream("/locations.txt")).getLines().toList
def locCheck(col: String): Boolean = locList.contains(col)
def locUDF = udf[Boolean, String](locCheck)
But when I add a toUpperCase to make it
val locList = Source.fromInputStream(getClass.getResourceAsStream("/locations.txt")).getLines().toList
def locCheck(col: String): Boolean = locList.contains(col.toUpperCase)
def locUDF = udf[Boolean, String](locCheck)
I run into a Failed to execute user defined function caused by java.lang.NullPointerException
I using the udf as df.filter(locUDF('location)).count()
What am I doing wrong here and how do I fix it ?
There is nothing wrong with the function or udf. The problem is with the data that comes into the udf.
Here in your case if the column location have a null values, When you pass those values to udf the value of col is null.
Then You get a NullPointerException when you call col.toUpperCase in case col is null.
You can simply check the null values in function
def locCheck(col: String): Boolean = if (col == null) false else locList.contains(col.toUpperCase)
Or you can use Options to handle this as
def locCheck(col: String): Boolean =locList.contains(Option(col).map(_.toUpperCase))
Hope this helps!

How to test function depended on another one in python

I need to test this type of code bellow:
list = [1,2,3,4]
def getData(list):
return list[0] + list[1]
def processData():
data = getData(list)
multiply = data*data
return multiply
def test_functions():
assert getData([0,1]) == 1
assert processData() == 1
How to tell the test I need data = getData([0,1]), so basically replace data with my test values.

How to xfail off a conditional involving a parametrization?

How to xfail off a conditional involving a parametrization?
The issue is that #pytest.mark.xfail(condition=(code == 123), reason="123 is an exception case") doesn't work because code is a parametrized variable. I tried some different things including static class members, globals, and setting it in the expected_setup fixture. None of these worked (as expected)
#pytest.mark.xfail(condition=(code == 123), reason="123 is an exception case")
E NameError: name 'code' is not defined
params = [
cls1,
cls2,
cls3,
cls4
]
#pytest.mark.parametrize('code', params, ids=list(map(str, params)))
class TestContextExit(object):
#pytest.fixture(autouse=True)
def expected_setup(self, code):
self.str1 = 'JETFUEL'
self.str2 = 'OPERATIONNORTHWOODS'
self.setup = NewStore(self.str1, self.str2, code)
def test1(self, code):
assert self.root.results.result_code == expected_result_code
assert self.root.results.ta['result_code'] == expected_result_code.code
assert self.root.results.result_code == expected_result_code
#pytest.mark.xfail(condition=(code == 123), reason="123 is an exception case")
def test2(self, code):
assert self.setup.root['code'] == code
#pytest.mark.xfail(condition=(code == 123), reason="123 is an exception case")
def test3(self, code):
assert self.setup.root['setup'] == NOERROR
Any ideas or patterns? Looking at the xfail pytest docs, I don't see any examples xfailing off parametrizations, except for the as part of the params. But in this case, the class is being parametrized and only two of the class tests turn into xfails, not all the tests.
You can use pytest.param with xfail mark as a param value in parametrization to xfail a param.
#pytest.mark.parametrize(code, [1,pytest.param(0,marks=pytest.mark.xfail(reason="reasons")]
def test_a():
assert code
This is used to mark certain parametrization value. This will xfail 2nd test.