Pytest fixture that parametrizes tests based on markers - python-3.x

Fixtures that parameterize tests can be created as such:
#pytest.fixture(scope="session", params=[“param1”, “param2"])
def fixture_that_parametrizes(request) -> str:
"""
This fixture parametrizes a test function,
as if #pytest.mark.parametrize(“param”, [“param1”, “param2”]) was used.
"""
return request.param
def parametrized_test(fixture_that_parametrizes):
“””
This test would run twice and print “param1” on the first
and “param2” on the second run. 
print(fixture_that_parametrizes)
assert 0
What I would like to do, is to create a fixture, that parametrizes tests differently, based on what markers are set within the test.
I haven’t found anything in the documentation regarding this. An idea I had was to create a parameterizing fixture with specific parameters dynamically within a fixture, but this approach seems a bit clunky.
Are there any better solutions or alternatives?

Related

Need Help creating class hierarchy in Python

I have a hierarchy of data that i would like to build using classes instead of hard coding it in. The structure is like so:
Unit (has name, abbreviation, subsystems[5 different types of subsystems])
Subsystem ( has type, block diagram(photo), ParameterModel[20 different sets of parameterModels])
ParameterModel (30 or so parameters that will have [parameter name, value, units, and model index])
I'm not sure how to do this using classes but what i have made kindof work so far is creating nested dictionaries.
{'Unit':{'Unit1':{'Subsystem':{'Generator':{Parameter:{'Name': param1, 'Value':1, 'Units': 'seconds'}
like this but with 10-15 units and 5-6 subsystems and 30 or so parameters per subsystem. I know using dictionaries is not the best way to go about it but i cannot figure out the class sharing structure or where to start on building the class structure.
I want to be able to create, read, update and delete, parameters in a tkinter gui that i have built as well as export/import these system parameters and do calculations on them. I can handle the calculations and the import export but i need to create classes that will build out this structure and be able to reference each individual unit/subsystem/parameter/value/etc
I know thats alot but any advice? ive been looking into the factory and abstract factory patterns in hope to try and figure out how to create the code structure but to no avail. I have experience with matlab, visual basic, c++, and various arduio projects so i know most basic programming but this inheritance class structure is something i cannot figure out how to do in an abstract way without hardcoding each parameter with giant names like Unit1_Generator_parameterName_parameter = ____ and i really dont want to do that.
Thanks,
-A
EDIT: Here is one way I've done the implementation using a dictionary but i would like to do this using a class that can take a list and make a bunch of empty attributes and have those be editable/callable generally like setParamValue(unit, susystem, param) where i can pass the unit the subsystem and then the parameter such as 'Td' and then be able to change the value of the key,value pair within this hierarchy.
def create_keys(list):
dict = {key: None for key in list}
return dict
unit_list = ['FL','ES','NN','SF','CC','HD','ND','TH'] #unit abbreviation
sub_list = ['Gen','Gov','Exc','PSS','Rel','BlkD']
params_GENROU = ["T'do","T''do","T'qo","T''qo",'H','D','Xd','Xq',"Xd'","Xq'","X''d=X''q",'Xl','S(1.0)','S(1.2)','Ra'] #parameter names
dict = create_keys(unit_list)
for key in dict:
dict[key] = create_keys(sub_list)
dict[key]['Gen'] = create_keys(params_GENROU)
and inside each dict[unit][Gen][ParamNames] there should be a dict containing Value, units(seconds,degrees,etc), description and CON(#basically in index for another program we use)

Mocking an Assert statement

I am teaching an introductory python course (python 3+Jupyter), and have been formulating assignments using nbgrader. For those not familiar, this basically means marking student's code via a set of assert statements. If the assert doesn't pass, they don't get the mark.
One of the tests that I want to perform is to check that students are writing their own tests. As a very simple example, let's imagine that they're supposed to be defining my_function, and all the tests that they want to run on it are supposed to be a series of assert statements inside a function do_tests() which will return True if all the tests pass.
One thing that I can obviously require of their code is that do_tests() passes simply by calling assert do_tests(). I can also check that it fails if I del my_function. However, I also want to check a bit more detail about the content of do_tests(). As a first step, I simply wanted to count the number of assert statements that they have used within the definition, and was intending to use unittest.mock.patch, trying to adapt the code from here. However, I could not figure out how to mock assert. I tried something like
from unittest.mock import patch
with patch('__main__.assert') as mock_assert:
do_tests()
but I just get an error that main does not have a method assert, and couldn't work out what module assert should be a part of.
As a crude interim, I have ended up doing
import inspect
lines = inspect.getsource(do_tests)
assert lines.count("\n assert")>=3,"You don't appear to have enough assert statements"
but obviously that doesn't give me access to any other features that mocking might offer.

Handle pytest cases where you want to trigger actions based on pass or fail of a testcase

I am running test cases using pytest; although I would like to collect some logs and zip everything, only if there is a failure
I did write the function that collect logs and zip it, although I can't find a way to actually trigger that for each failed case. I did implement a solution using the #classmethod decorators for setUpClass and tearDownClass; but this happen only after all the tests have been ran, and not when a specific test fail.
In each test I run a simple assertFalse(a < b, "the test did fail". I would like to trigger the function that does the log collection only when that condition is actually triggered.
Seems that there is no direct way to do it in the assert statement, or I was not able to find a way for it.
I just used try-catch and in the try I raise an exception,and in the catch code I call the function. Not sure if this is the best way, but it works in my case
try:
if (a < b):
raise ValueError ("wrong output, collecting logs")
except ValueError:
# call function to parse logs
self.parseoutputonerror(a, b, "/tmp/out.zip")

Add additional operations to existing method which is in Python module

I have a python module which has several methods:
module.py
def a():
return "This is a method"
I want to add some additional functionality to method a by calling it from script to avoid modification in module itself.
How can I add additional operations or arguments to that module calling it from script?
For example I imported module.py in my script and in that script I add two arguments to method "a" and addition of those arguments in addition to:
return "This is a method"
Well, you cannot really change any imported methods as far as I am aware. That does not mean it is completely impossible, I just wouldn't know how.
Question is though if that is actually what you want (as I believe it is a very uncommon way of handling code and I am guessing not an advisable one)?
Could it be that what you actually want to achieve is something more like this:
module_script.py
def a(variable):
return_value = "This is a " + str(variable) + " method!"
return return_value
second_script.py
import module_script
print(module_script.a("nice"))
The output of the second script would be:
"This is a nice method!"

call different class functions or a combo of class functions depending on arg in python

I have a subparser named app01. It has two arguments --delete-user, and --delete-hash. I've set the default function to call the function check_app
the check_app function is something like this:
def check_app(args):
a = App()
if args.user:
# run function01 from App() class to delete user account
elif args.hash:
# run function02 from App() class delete user hash
else:
# run both functions to delete user and hash
How do i get that to work without having to add both function01 and function02 into the else block. Or is that the only way?
I think what code you have is decent.
If you want what you want this for purely aesthetic reasons, let me warn you that the code maintainability will drop substantially. You can see the answer given by Ronan B already seems pretty confusing and if you're the person trying to understand it, it feels like too much work to decipher.
But if you still want me to titillate your senses, I may as well suggest a simpler version:
def check_app(args):
a = App()
if not args.user:
# run #02 < note #2
if not args.hash:
# run #01 < note #1
This is of course assuming that if both functions #1 and #2 need to run, no arguments are given, instead of both arguments being given, as is typically intuitive.

Resources