How to write python test case for Exception block effectively - python-3.x

I am trying to write test case for exception block for my python code. The test code passes in my local but fails in sonar scan. The sample code is below :
def testMethod(var1: List[str]):
try:
Some code blocks
for item in var1:
some block of codes
except Exception as e:
return var1
My sample test code is below:
class UnitTests(unittest.TestCase):
def test_testMethod(self):
from main import testMethod
testMethod(pd.Dataframe())
self.assertRaises(AttributeError)
Th above test case passes in my machine but fails during Sonar scan. What am I missing??

Related

Pytest Exit Codes

I've built my pytest class in the following manner:
class Test_Exit_Code(object):
def setup_class(cls):
If 2==2:
# stop execution of the test class
def test_a(self):
assert True==True
As you can see inside the setup_class method i've inserted an IF , what i want to achieve in the if section is that if a certain condition appears to be true instead of the comment i want to return exit code 5 , i.e. no tests were collected .
so far i haven't found any way to do it.
You could try calling pytest.exit(). Also it seems you are missing the classmethod decorator
class Test_Exit_Code:
#classmethod
def setup_class(cls):
If 2==2:
pytest.exit("test exit code setup failed", returncode=5)
pytest.exit
Setup / Teardown

Pytest Cov Report Missing Mock Exception Returns

I'm a Network Engineer who is trying to write some Python, so very much still learning each day. I have an issue with Unit Testing and Pytest coverage reports. I think I understand the concept of unit tests and pytest.
I have a function that does a DNS lookup using socket
def get_ip(d):
"""Returns the first IPv4 address that resolves from 'd'
Args:
d (string): string that needs to be resolved in DNS.
Returns:
string: IPv4 address if found
"""
logger.info("Returns IP address from hostname: " + d)
try:
data = socket.gethostbyname(d)
ip_addr = repr(data).strip("'")
logger.debug("IP Address Resolved to: " + ip_addr)
return ip_addr
except socket.gaierror:
return False
I have written a unit test which passes fine. I'm using pytest-mock to handle the mocking of the socket for the DNS lookup. Side Effect seems to be mocking the Exception and I've set a return_value as False and I assuming I have asserted that False is returned, the test passes ok which is why I'm assuming that my test is ok.
import pytest
import pytest_mock
import socket
from utils import network_utils
#pytest.fixture
def test_setup_network_utils():
return network_utils
def test_get_ip__unhappy(mocker, test_setup_network_utils):
mocker.patch.object(network_utils, 'socket')
test_setup_network_utils.socket.gethostbyname.side_effect = socket.gaierror
with pytest.raises(Exception):
d = 'xxxxxx'
test_setup_network_utils.socket.gethostbyname.return_value = False
test_setup_network_utils.get_ip(d)
assert not test_setup_network_utils.socket.gethostbyname.return_value
test_setup_network_utils.socket.gethostbyname.assert_called_once()
test_setup_network_utils.socket.gethostbyname.assert_called_with(d)
The pytest-cov report shows the return False line as not being covered.
pytest --cov-report term-missing:skip-covered --cov=utils unit_tests
network_utils.py 126 7 94% 69
Line 69 is the below line of code in function
except socket.gaierror:
return False <<<<<<<< This is missing from the report
Any pointers would be appreciated as to why the return of False isn't being declared as covered. Like I said above I'm pretty new to Python and coding and this is my 1st question on Stackoverflow. Hopefully I've explained what my issue and have provided enough information for some guidance.
When you declare
mocker.patch.object(network_utils, 'socket')
you are replacing the whole socket module with a single mock, so everything in the socket module becomes a mock too, including socket.gaierror. Thus, when trying to catch socket.gaierror while running the test, Python will complain that it is not an exception (does not subclass from BaseException) and fail. Therefore, the desired return line is not executed.
Overall, your test looks overengineered and contains a lot of unnecessary code. What do you need the test_setup_network_utils for? Why are you catching an arbitrary exception in test? A revisited test_get_ip__unhappy that covers the complete code in the gaierror case:
def test_get_ip__unhappy(mocker):
# test setup: patch socket.gethostbyname so it always raises
mocker.patch('spam.socket.gethostbyname')
spam.socket.gethostbyname.side_effect = socket.gaierror
# run test
d = 'xxxxxx'
result = spam.get_ip(d)
# perform checks
assert result is False
spam.socket.gethostbyname.assert_called_once()
spam.socket.gethostbyname.assert_called_with(d)
Of course, spam is just an example; replace it with your actual import.

Test step should stop when testStep Script assertion fails

i have to run the testStep multiple time with different data loading from external file(using file object looping to run the testSteps for each record) and validate the data from response for each value.
i'm able to do that and its executing and works fine. but when ever assert fails execution is not stoping and it will continue and shows testStep is passed.
i can see the failed in "script log" windows whenever it fails because i'm using log.info with run.status
and i check checkbox for "abort if test if any error occurs" and "failed tes cases if testStep fails" on test case options.
still it continue executing the test cases
Important Note: above scenario happens when assert fails in middle of the records, if it is fails for last record then its stopping the execution.
Code which i used
This Groovy script code: file iterates the testStep as per the no of rows in file
// Get tha path to an input file from a custom property
def inputFilePath = testRunner.testCase.testSuite.getPropertyValue( "inputFile" )
// Get the test case we want to Run
def tc=testRunner.testCase.testSuite.testCases["DetectRules"].testSteps["Rules_DENF_224"]
// Iterate through the input file
File file = new File(inputFilePath.toString()).eachLine{
// Set Test Suite custom properties
testRunner.testCase.testSuite.setPropertyValue( "InValue", it.split(",")[0] )
testRunner.testCase.testSuite.setPropertyValue( "OutValue", it.split(",")[1] )
testRunner.testCase.testSuite.setPropertyValue( "outDesc", it.split(",")[2] )
def runner = tc.run(testRunner,context)
//Get the Json response from execution
def FraudReq = testRunner.testCase.testSuite.testCases["DetectRules"].testSteps["Rules_DENF_224"].testRequest.response.responseContent
// Log info to a output
log.info "Execution of test case with Input value: ${it.split(",")[0]} and expected returned value: ${it.split(",")[1]} and Expected Description is: ${it.split(",")[2]} ${runner.status}"
// Sleep for a second since were using public service
sleep 500
}
this is testStep --> Script Assertion: section
import groovy.json.JsonSlurper
def response= messageExchange.response.responseContent
def jsonsl= new JsonSlurper().parseText(response)
def expected=context.getTestCase().getPropertyValue(“rule number”)
assert expected==jsonsl.results[4].id
if above assert fails then testStep should stop ,but testStep failing but execution is not stopped.
any help appreciated

How to mock a BulkWriteException in python?

I need to get the information contained in the exception. This is the code I use.
try:
result = yield user_collection.insert_many(content, ordered=False)
except BulkWriteError as e:
print (e)
And in my test when I get into the except with this line,
self.insert_mock.side_effect = [BulkWriteError('')]
it returns me
batch op errors occurred
instead of a MagicMock or a Mock.
How can I mock the BulkWriteError and give it a default return_value and see it when I use print(e)?
Something like this should allow you to test your print was called correctly.
import builtins # mockout print
class BulkWriteErrorStub(BulkWriteError):
''' Stub out the exception so you can bypass the constructor. '''
def __str__:
return 'fake_error'
#mock.patch.object('builtins', 'print')
def testRaisesBulkWrite(self, mock_print):
...
self.insert_mock.side_effect = [BuilkWriteErrorStub]
with self.assertRaises(...):
mock_print.assert_called_once_with('fake_error')
I haven't tested this so feel free to edit it if I made a mistake.

Run a test step in Script assertion SOAP UI

I have 5 test steps in a test case and i want to write a script assertion for a test step
Like
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def httpResponseHeaders = context.testCase.testSteps["Step1"].testRequest.response.responseHeaders
def httpStatus = httpResponseHeaders["#status#"]
def httpStatusCode = (httpStatus =~ "[1-5]\\d\\d")[0]
if (httpscode == "500")
I want to re-run the test step named as step 1
I know that testRunner class is not present in Script assertion is there a way to do it with messageExchange variable class
I saw an answer on stack overflow
`messageExchange.modelItem.testStep.testCase.getTestStepByName("Step1").run(context.getTestRunner(),context)`
I tried the code but as soon as i click run SOAP UI hangs and I have to force close the SOAP UI application
To run a test step from script assertion you may use this
import com.eviware.soapui.support.types.StringToObjectMap
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner
def Runner = new WsdlTestCaseRunner(messageExchange.modelItem.testStep.testCase, new StringToObjectMap())
yourTestStep= messageExchange.modelItem.testStep.testCase.testSuite.project.testSuites["ScriptLibrary"].testCases["Library"].testSteps["Lib"]
yourTestStep.run(Runner,context)
Your code is fine, except your logic is flawed, because you encounter the error 500 for the first time and then you call the same step again and it fails again with 500 and so on. You would need to get different status, before your Java runs out of memory.
So if you want to do something like that, you have to implement some kind of counter (using TestCase, TestSuite, Project or Global property) to perform this loop only several times and then fail.
Anyway this worked for me:
def utilitiesSuite = messageExchange.modelItem.testStep.testCase
.testSuite.project.getPropertyValue('utilitiesTestSuiteName');
messageExchange.modelItem.testStep.testCase.testSuite.project
.testSuites[utilitiesSuite].testCases["Test Case utility name"]
.run(null, true);
In this case we have all "utilities" = test cases with some often needed functionality in a dedicated test suite and I wanted its name to be possible to set up on Project level, of coures the Test Suite name can be put there directly as for example "Utilities'.
Also i have tried with this:
context.getTestRunner()
As the first parameter in the methor run instead of the null, but it worked only when testing the one requirement, not when running whole test case or test suite.
I let here another example that worked for me.
It's an assertion script, which runs a testStep basing on a response node value.
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context );
def holder = groovyUtils.getXmlHolder( "yourTestStep#response" );
def myValue = holder.getNodeValue( "//theNameSpace:yourNode" );
if(myValue == 'whateverYouWant'){
//com.eviware.soapui.support.UISupport.showInfoMessage(myValue);
def Runner = new com.eviware.soapui.impl.wsdl.testcase.WsdlTestCaseRunner(
messageExchange.modelItem.testStep.testCase, new com.eviware.soapui.support.types.StringToObjectMap());
def mySteps= messageExchange.modelItem.testStep.testCase.testSuite.project.testSuites["yourTestSuite"].testCases["yourTestCase"].testSteps["yourTestStep"];
mySteps.run(Runner,context);
}

Resources