Does pytest provide a way of automatically reading properties for a test from a yml or conf file? - python-3.x

I'm using Python 3.8 and pytest for unit testing. I have tests similar to the following
def test_insert_record(az_sql_db_inst):
    """."""
    foreign_key_id = 10
I don't like hard-coding "10" in the file, and would prefer this be stored in some external configuration file where other tests can also access the value. Does pytest provide a way to do this (to load the values from a properties or yml file)? I could just open a file on my own, e.g.
def test_insert_record(az_sql_db_inst):
    """."""
file = open('test.txt')
for line in file:
fields = line.strip().split()
foreign_key_id = fields[0]
but it seems like there is something that can automatically do that for me.

If you simply want to initialize some constants, a separated config.py would do the trick.
from config import foreign_key_id
And PyYAML package would be good if you prefer general-purpose text files.
However, if you want to specify expected test results or even different results depending on scenarios, #pytest.mark.parametrize may be a good option.

Related

Best practice to load config file in python

I am going to read data from a config.ini file using configparser, but I'm wondering what the best practice is.
Should I:
Load the config file once in my main method when the application starts, then call the variable in other modules (something like the below):
from main import config
import configparser in each module where I need information from the config file (I feel like this is not the right way because I would have the same code in multiple places).
Any advice would be appreciated

How to import whole python file and not break F403 flake8 rule?

Imports like this:
from .file import *
are "anti-patterns". How can I import one python file into another, without breaking flake8 F430 rule? I have settings.py in the Django project that I want to "overwrite" in test_settings.py like this,
from settings import *
# make tests faster
DATABASES['default'] = {'ENGINE': 'django.db.backends.sqlite3'}
to test with in-memory database, and I cant figure out how to do it without breaking the rule.
According to authors of the book "Two Scoops of Django 3.x" this is actually an exception when they advocate using
import *
the singular case of Django setting modules we want to override all the namespace
in order to allow usage of multiple settings files. Therefore in this situation, the best solution is to exclude test_settings.py from the flake8 scan, in the flake8 configuration file.

How do I read Windows Registry file to check for values? [Python]

I am trying to perform auditing checks on Windows Registry file (.reg file, offline) and I am hoping that I can utilize Python to perform a check on the reg file.
For example (pseudo code):
#Configure registry policy processing: Do not apply during periodic background processing
testloc = "C:\\Users\\test.reg"
datafile = open(testloc, "r")
read = datafile.read()
find(Software\Policies\Microsoft\Windows\Group Policy\{35378EAC-683F-11D2-A89A-00C04FBBCFA2})
check(NoBackgroundPolicy) #check if dword value is correct
if(dword == correct):
print("correct")
else:
print("wrong")
I have tried looking at _winreg but it seems like it does a check on a live system using Windows API. Another issue is the large .reg file size(~200MB).
How can I perform such a check using Python?
I don't know if there's a lib that can read .reg files specifically, but from what it looks like it's just an INI file with an extra version information at the top.
Here's an example of how you could use the configparser module for that. Some notes:
.reg files are encoded in utf16
Before giving the file to the ConfigParser, a readline will skip the version info (something like Windows Registry Editor Version 5.00). Otherwise it will result in a MissingSectionHeaderError.
The names of values include quotation marks, which means you need to add them explicitly when looking up the value in the key.
import configparser
testloc = "C:\\Users\\test.reg"
regdata = configparser.ConfigParser()
with open(testloc, "r", encoding="utf-16") as f:
f.readline() # skip version info in first line
regdata.read_file(f)
key = regdata[r"HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Group Policy\{35378EAC-683F-11D2-A89A-00C04FBBCFA2}"]
value = key['"NoBackgroundPolicy"']
print(value)
There may be drawbacks of doing it this way though, for example in how the values you obtain are formatted.

How do i make all rows of pytest-html single html report result file default to a collapsed state?

I use the pytest runner to get the output of results from my automated test frameworks (Selenium and RestAPI tests). I use the pytest-html plugin to generate a single page html result file at the end of the test. I initiate the test run with the following command (from an active VirtEnv session).
python -m pytest -v --html="api_name_test.html" --self-contained-html
(it's a little more complicated in that I use a powershell script to run this and provide a datetime stamped result file name and email the file when it's finished but it's essentially the above command)
When the reports are generated and I open this report html I find that all the non passing tests are expanded. I want to make it so all rows are collapsed by default (Failed, XFailed, Error etc..).
My project contains a conftest.py file at the diretory root and a pytest.ini file where I specify the directory for the test scripts
In the conftest.py file in my simplest projects, I have one optional hook to obtain the target url of the tests and put that in the report summary:
import pytest
from py._xmlgen import html
import os
import rootdir_ref
import simplejson
#pytest.mark.optionalhook
def pytest_html_results_summary(prefix):
theRootDir = os.path.dirname(rootdir_ref.__file__)
credentials_path = os.path.join(theRootDir, 'TestDataFiles', 'API_Credentials.txt')
target_url = simplejson.load(open(credentials_path)).get('base_url')
prefix.extend([html.p("Testing against URL: " + target_url)])
The Github page mentions that a display query can be used to collapse rows with various results, but it doesn't mention where this information is entered.
https://github.com/pytest-dev/pytest-html
"By default, all rows in the Results table will be expanded except those that have Passed. This behavior can be customized with a query parameter: ?collapsed=Passed,XFailed,Skipped"
Currently I'm unsure if the ?collapsed=... line goes in the command line, or the conftest as a hook, or do I need to edit the default style.css or main.js that comes with the pytest-html plugin? (Also i'm not familiar with css and only know a small amount of html). I'm assuming it goes in the conftest.py file as a hook but don't really understand how to apply it.
https://pytest-html.readthedocs.io/en/latest/user_guide.html#display-options
Auto Collapsing Table Rows
By default, all rows in the Results table will be expanded except those that have Passed.
This behavior can be customized either with a query parameter: ?collapsed=Passed,XFailed,Skipped or by setting the render_collapsed in a configuration file (pytest.ini, setup.cfg, etc).
[pytest]
render_collapsed = True
NOTE: Setting render_collapsed will, unlike the query parameter, affect all statuses.

How to get random row from file in JMeter

I'm looking for way how to get random row from file in JMeter.
I would be appreciate for any suggestions.
Not sure regarding groovy, maybe there is an easier way, but for instance you can do it with Beanshell Sampler using the following code:
import org.apache.commons.io.FileUtils; //necessary import
List lines = FileUtils.readLines(new File("/path/to/your/file")); // read file into lines array
int random = new Random().nextInt(lines.size()); // get random line number
String randomLine = lines.get(random); // get random line
vars.put("randomLine", randomLine); // store the random line into ${randomLine} variable
substitute /path/to/your/file with relative or absolute path to the file you want the random line from
you will be able to access the random line as ${randomLine} where required
See How to Use BeanShell: JMeter's Favorite Built-in Component guide for more information on using JMeter and Java APIs from Beanshell test elements in your JMeter test
N.B. The above code is valid groovy code as well
This should be possible using a bean shell controller. Here you will need to do bit of programming to achieve the desired behaviour.
There is an easy way to achieve the desired outcome.
Introduce a ransom timer into your thread group.
The timer will ensure the randomness of the threads.
Configure a CSV confit element to read data from a file.
Ensure the file is shared with all the threads.
you can get a random var
random__Random(1,9)
//syntax: __Random(start,end)
Then you can pull out
File fileInstance = new File("path/yourfile.txt");
readerInstance = new IndexedFileReader(fileInstance);
lines = readerInstance.readLines(randomIdx, randomIdx+1);
readLines takes a start and an end line number..
However if you are using anything other then very small files, with low iterations I really suggest you read the entire file into a buffer, and use the random var to pull lines from that
You can also use the Random CSV Data Set Config Plugin Jmeter plugin by Blazemeter. It has all the randomising a regualr user will want on top of the conventional JMeters CSV Data Set Config.

Resources