How to excuite test classes in suite one after the other? - python

I have written a test suite to execute all my test classes one after the other .
But the problem is that while executing , its taking the methods from both class and executing at once.
so i want to write a code where all methods in one class will be executed
and later it will proceed to the next test class.
Test class code
from pages.Home.hamburger_page import HamburgerPage
from utilites.testStatus import TestStatus
import pytest
import unittest
#pytest.mark.usefixtures("oneTimeSetUp", "setUp")
class hamburgerTest(unittest.TestCase):
#pytest.fixture(autouse=True)
def classSetup(self, oneTimeSetUp):
self.ha = HamburgerPage(self.driver)
self.ts = TestStatus(self.driver)
#pytest.mark.run(order=1)
def test_hamburger_menu_latest_WAF021(self):
result = self.ha.find_latest()
self.ts.markFinal("To find latest link", result, "Click on latest link")
#pytest.mark.run(order=2)
def test_hamburger_menu_top__WAF022(self):
result = self.ha.find_topics_links()
self.ts.markFinal("To find top link", result, "Click on top link")
#pytest.mark.run(order=3)
def test_hamburger_menu_badges__WAF023(self):
result = self.ha.find_badges()
self.ts.markFinal("To find badges link", result, "Click on badges link")
#pytest.mark.run(order=4)
def test_hamburger_menu_users__WAF024(self):
result = self.ha.find_users()
self.ts.markFinal("To find user link ", result,"Click on users link")
#pytest.mark.run(order=5)
def test_hamburger_menu_groups__WAF025(self):
result = self.ha.find_groups()
self.ts.markFinal("To find groups link", result, "Click on groups link")
#pytest.mark.run(order=6)
def test_hamburger_menu_announcements__WAF026(self):
result = self.ha.find_announcements()
self.ts.markFinal("To find announcements link", result, "Click on announcements link")
Second Test
from pages.Home.topic_page import topicPage
from utilites.testStatus import TestStatus
import pytest
import unittest
import time
#pytest.mark.usefixtures("oneTimeSetUp","setUp")
class TopicTest(unittest.TestCase):
#pytest.fixture(autouse=True)
def classSetup(self,oneTimeSetUp):
self.tp = topicPage(self.driver)
self.ts = TestStatus(self.driver)
#pytest.mark.run(order=1)
def test_header_login(self):
self.tp.find_header_logIn()
#pytest.mark.run(order=2)
def test_validLogin(self):
self.tp.getelements("xxxxxx#xxx.com", "xxxxx")
time.sleep(3)
#pytest.mark.run(order=3)
def test_FirstLinkInAnnouncements(self):
self.tp.find_first_announcement_link()
time.sleep(3)
#pytest.mark.run(order=5)
def test_TitleVerfication(self):
self.tp.find_title()
time.sleep(5)
#pytest.mark.run(order=4)
def test_ReplyDropDown(self):
self.tp.find_scrollupfull()
time.sleep(4)
self.tp.find_topic_page_reply()
Test Suite
import unittest
from tests.Home.hamburger_test import hamburgerTest
from tests.Home.topic_test import TopicTest
# Get all tests from the test classes
tc1 = unittest.TestLoader().loadTestsFromTestCase(hamburgerTest)
tc2 = unittest.TestLoader().loadTestsFromTestCase(TopicTest)
# Create a test suite combining all test classes
Test1 = unittest.TestSuite([tc1, tc2])
unittest.TextTestRunner(verbosity=2).run(Test1)

you should execute tc1 and tc2 separately. for eg.
Test1 = unittest.TestSuite([tc1])
Test2 = unittest.TestSuite([tc2])
unittest.TextTestRunner(verbosity=2).run(Test1)
unittest.TextTestRunner(verbosity=2).run(Test2)
Hope this will solve your issue.

You are using pytest-ordering plugin (https://pytest-ordering.readthedocs.io/en/develop/).
You're setting the order in which tests should be executed. It makes pytest execute tests from highest order (1) to lowest. Tests with the same order can be found in both classes, which is why pytest is jumping between classses.

Related

How do I include both data and state dependencies in a Prefect flow?

This seems like it should be simple, but I can't figure out how to include both state and data dependencies in a single flow. Here is what I attempted (simplified):
def main():
with Flow("load_data") as flow:
test_results = prepare_file1()
load_file1(test_results)
participants = prepare_file2()
load_file2(participants)
email = flow.add_task(EmailTask(name='email', subject='Flow succeeded!', msg='flow succeeded', email_to='xxx', email_from='xxx', smtp_server='xxx',smtp_port=25, smtp_type='INSECURE',))
flow.set_dependencies(task=email, upstream_tasks=[load_file1,load_file2])
flow.visualize()
I get the following graph:
Which means that load_file1 and load_file2 run twice. Can I just set up an additional dependency so that email runs when the two load tasks finish?
The issue is how you add the task to your Flow. When using tasks from the Prefect task library, it's best to first initialize those and then call those in your Flow as follows:
send_email = EmailTask(name='email', subject='Flow succeeded!', msg='flow succeeded', email_to='xxx', email_from='xxx', smtp_server='xxx', smtp_port=25, smtp_type='INSECURE')
with Flow("load_data") as flow:
send_email()
Or alternatively, do it in one step with double round brackets EmailTask(init_kwargs)(run_kwargs). The first pair of brackets will initialize the task and the second one will call the task by invoking the task's .run() method.
with Flow("load_data") as flow:
EmailTask(name='email', subject='Flow succeeded!', msg='flow succeeded', email_to='xxx', email_from='xxx', smtp_server='xxx', smtp_port=25, smtp_type='INSECURE')()
The full flow example could look as follows:
from prefect import task, Flow
from prefect.tasks.notifications import EmailTask
from prefect.triggers import always_run
#task(log_stdout=True)
def prepare_file1():
print("File1 prepared!")
return "file1"
#task(log_stdout=True)
def prepare_file2():
print("File2 prepared!")
return "file2"
#task(log_stdout=True)
def load_file1(file: str):
print(f"{file} loaded!")
#task(log_stdout=True)
def load_file2(file: str):
print(f"{file} loaded!")
send_email = EmailTask(
name="email",
subject="Flow succeeded!",
msg="flow succeeded",
email_to="xxx",
email_from="xxx",
smtp_server="xxx",
smtp_port=25,
smtp_type="INSECURE",
trigger=always_run,
)
with Flow("load_data") as flow:
test_results = prepare_file1()
load1_task = load_file1(test_results)
participants = prepare_file2()
load2_task = load_file2(participants)
send_email(upstream_tasks=[load1_task, load2_task])
if __name__ == "__main__":
flow.visualize()

Using same data in different states of SMACH Concurrent-container

Let's say we have a concurrent SMACH container sm_con which includes two state machines SM1 and SM2. I need to find a way for SM1 to continuously update some data and for SM2 to access (and eventually also modify) the same data. I thought about solving this by passing the userdata of sm_con to SM1 and SM2 as input- and output-keys hoping that if SM1 modifies the data it would automatically overwrite sm_cons userdata (kind of like working with pointers in c++) but this doesn't work.
The corresponding code would look like this:
import smach
import smach_ros
import rospy
class st1(smach.State):
def __init__(self, outcomes=['successful', 'preempted']):
smach.State.__init__(self, outcomes, input_keys=['in_test'], output_keys=['out_test'])
def execute(self, userdata):
if self.preempt_requested():
self.service_preempt()
return 'preempted'
rospy.logerr('test 1: '+str(userdata.in_test))
userdata.out_test=userdata.in_test+1
return 'successful'
class st2(smach.State):
def __init__(self, outcomes=['successful', 'preempted']):
smach.State.__init__(self, outcomes, input_keys=['in_test'])
def execute(self, userdata):
#time.sleep(2)
if self.preempt_requested():
self.service_preempt()
return 'preempted'
rospy.logerr('test 2: ' + str(userdata.in_test))
return 'successful'
if __name__=="__main__":
rospy.init_node('test_state_machine')
sm_con = smach.Concurrence(outcomes=['success'],
default_outcome='success'
)
sm_con.userdata.testdata = 0
with sm_con:
sm_1 = smach.StateMachine(outcomes=['success', 'preempted'], input_keys=['testdata'], output_keys=['testdata'])
with sm_1:
smach.StateMachine.add('ST1', st1(),
remapping={'in_test': 'testdata', 'out_test': 'testdata'},
transitions={'successful': 'ST1'})
sm_2 = smach.StateMachine(outcomes=['success', 'preempted'], input_keys=['testdata'])
with sm_2:
smach.StateMachine.add('ST2', st2(),
remapping={'in_test':'testdata'},
transitions={'successful': 'ST2'})
smach.Concurrence.add('SM1', sm_1)
smach.Concurrence.add('SM2', sm_2)
# Execute SMACH plan
outcome = sm_con.execute()
print('exit-outcome:' + outcome)
# Wait for ctrl-c to stop the application
rospy.spin()
Running this code, the output 'test 1: ...' shows that inside SM1 the userdata gets incremented while the output 'test 2: ...' shows that SM2 doesn't access the incremented data as the output remains 0.
How can I modify some data in SM1 and access the modified data in SM2?
I found a workaround for this using mutable objects like described here.
Applied on the code above, it would look like the following:
import smach
import smach_ros
import rospy
class st1(smach.State):
def __init__(self, outcomes=['successful', 'preempted']):
smach.State.__init__(self, outcomes, input_keys=['in_test'])
def execute(self, userdata):
if self.preempt_requested():
self.service_preempt()
return 'preempted'
rospy.logerr('test 1: '+str(userdata.in_test))
userdata.in_test[0]=userdata.in_test[0]+1
return 'successful'
class st2(smach.State):
def __init__(self, outcomes=['successful', 'preempted']):
smach.State.__init__(self, outcomes, input_keys=['in_test'])
def execute(self, userdata):
#time.sleep(2)
if self.preempt_requested():
self.service_preempt()
return 'preempted'
rospy.logerr('test 2: ' + str(userdata.in_test[0]))
return 'successful'
if __name__=="__main__":
rospy.init_node('test_state_machine')
sm_con = smach.Concurrence(outcomes=['success'],
default_outcome='success'
)
sm_con.userdata.testdata = [0]
with sm_con:
sm_1 = smach.StateMachine(outcomes=['success', 'preempted'], input_keys=['testdata'])
with sm_1:
smach.StateMachine.add('ST1', st1(),
remapping={'in_test': 'testdata'},
transitions={'successful': 'ST1'})
sm_2 = smach.StateMachine(outcomes=['success', 'preempted'], input_keys=['testdata'])
with sm_2:
smach.StateMachine.add('ST2', st2(),
remapping={'in_test':'testdata'},
transitions={'successful': 'ST2'})
smach.Concurrence.add('SM1', sm_1)
smach.Concurrence.add('SM2', sm_2)
# Execute SMACH plan
outcome = sm_con.execute()
print('exit-outcome:' + outcome)
# Wait for ctrl-c to stop the application
rospy.spin()
Since this is only a workaround, refer to my corresponding issue-post here for more information.

How to mock googleapiclient.discovery.build

I am trying to mock the result of API call made to compute engine to list VMs. But unfortunately couldn't mock an exact function.
I've tried using PATCH and MOCK methods to mock specific calls made, still unsuccessful
code.py file looks likes this
import googleapiclient.discovery
import logging
class Service:
def __init__(self, project, event):
self.project_id = project
self.compute = googleapiclient.discovery.build('compute', 'v1',
cache_discovery=False)
self.event = event
self.zones = self._validate_event()
def _validate_event(self):
if "jsonPayload" not in self.event:
zones = self.compute.zones().list(
project=self.project_id).execute()['items']
else:
zones = self.compute.zones().get(project=self.project_id,
zone=self.event["jsonPayload"]
["resource"]["zone"]).execute()
logging.debug(f"Identified Zones are {zones}")
return [zone["name"] for zone in zones]
My test file looks like this
# in-built
from unittest import TestCase
from unittest.mock import patch
# custom
import code
class TestServiceModule(TestCase):
def setUp(self):
self.project_id = "sample-project-id"
#patch('code.googleapiclient.discovery')
def test__validate_event_with_empty_inputs(self, mock_discovery):
mock_discovery.build.zones.list.execute.return_value = {"items": [
{
"name": "eu-west-1"
}
]}
obj = code.Service(event={}, project=self.project_id)
print(obj.zones)
In the above test case, I Expected to see "eu-west-1" as the value when I print obj.zones
You didn't mock the googleapiclient.discovery.build method correctly. Here is the unit test solution:
E.g.
code.py:
import googleapiclient.discovery
import logging
class Service:
def __init__(self, project, event):
self.project_id = project
self.compute = googleapiclient.discovery.build('compute', 'v1', cache_discovery=False)
self.event = event
self.zones = self._validate_event()
def _validate_event(self):
if "jsonPayload" not in self.event:
zones = self.compute.zones().list(project=self.project_id).execute()['items']
else:
zones = self.compute.zones().get(project=self.project_id,
zone=self.event["jsonPayload"]["resource"]["zone"]).execute()
logging.debug(f"Identified Zones are {zones}")
return [zone["name"] for zone in zones]
test_code.py:
from unittest import TestCase, main
from unittest.mock import patch
import code
class TestService(TestCase):
def setUp(self):
self.project_id = "sample-project-id"
#patch('code.googleapiclient.discovery')
def test__validate_event_with_empty_inputs(self, mock_discovery):
# Arrange
mock_discovery.build.return_value.zones.return_value.list.return_value.execute.return_value = {
"items": [{"name": "eu-west-1"}]}
# Act
obj = code.Service(event={}, project=self.project_id)
# Assert
mock_discovery.build.assert_called_once_with('compute', 'v1', cache_discovery=False)
mock_discovery.build.return_value.zones.assert_called_once()
mock_discovery.build.return_value.zones.return_value.list.assert_called_once_with(project='sample-project-id')
mock_discovery.build.return_value.zones.return_value.list.return_value.execute.assert_called_once()
self.assertEqual(obj.zones, ["eu-west-1"])
if __name__ == '__main__':
main()
unit test result with coverage report:
.
----------------------------------------------------------------------
Ran 1 test in 0.002s
OK
Name Stmts Miss Cover Missing
-----------------------------------------------------------------------
src/stackoverflow/56794377/code.py 14 1 93% 16
src/stackoverflow/56794377/test_code.py 16 0 100%
-----------------------------------------------------------------------
TOTAL 30 1 97%
Versions:
google-api-python-client==1.12.3
Python 3.7.5

assert pytest command has been run

I have an django app route that will run a pytest.main() command if some conditions are met:
def run_single_test(request, single_test_name):
# get dict of test names, test paths
test_dict = get_single_test_names()
# check to see if test is in the dict
if single_test_name in test_dict:
for test_name,test_path in test_dict.items():
# if testname is valid run associated test
if test_name == single_test_name:
os.chdir('/lib/tests/')
run_test = pytest.main(['-v', '--json-report', test_path])
else:
return 'The requested test could not be found.'
I would like to include a unit test that validates run_test has been executed.
What is the best approach to doing this? Mock and unittest are new to me.
I tried messing around with stdout:
def test_run_single_test_flow_control(self):
mock_get = patch('test_automation_app.views.get_single_test_names')
mock_get = mock_get.start()
mock_get.return_value = {'test_search': 'folder/test_file.py::TestClass::test'}
results = run_single_test('this-request', 'test_search')
output = sys.stdout
self.assertEqual(output, '-v --json-report folder/test_file.py::TestClass::test')
but this returns:
<_pytest.capture.EncodedFile object at XXXXXXXXXXXXXX>
Here are two example tests that verify that pytest.main is invoked when a valid test name is passed and not invoked otherwise. I also added some different invocations of mock_pytest_main.assert_called as an example; they all do pretty much the same, with extra check for args that were passed on function call. Hope this helps you to write more complex tests!
from unittest.mock import patch
from test_automation_app.views import run_single_test
def test_pytest_invoked_when_test_name_valid():
with patch('pytest.main') as mock_pytest_main, patch('test_automation_app.views.get_single_test_names') as mock_get:
mock_get.return_value = {'test_search': 'folder/test_file.py::TestClass::test'}
results = run_single_test('this-request', 'test_search')
mock_pytest_main.assert_called()
mock_pytest_main.assert_called_with(['-v', '--json-report', 'folder/test_file.py::TestClass::test'])
mock_pytest_main.assert_called_once()
mock_pytest_main.assert_called_once_with(['-v', '--json-report', 'folder/test_file.py::TestClass::test'])
def test_pytest_not_invoked_when_test_name_invalid():
with patch('pytest.main') as mock_pytest_main, patch('test_automation_app.views.get_single_test_names') as mock_get:
mock_get.return_value = {'test_search': 'folder/test_file.py::TestClass::test'}
results = run_single_test('this-request', 'test_non_existent')
mock_pytest_main.assert_not_called()

How to call a function from another class in python->sikuli?

How can i access methods of channel1 in channel2 so that test_script1,test_script2 is execute first and then test_script3,test_script4.
Note:- The main issue is when i am executing
suite1= unittest.TestLoader().loadTestsFromTestCase(channel1) and
suite2= unittest.TestLoader().loadTestsFromTestCase(channel2), i am getting two reprort tables.
But instead i want them to merge in one table consisting data of channel1 and channel2 classes both.
from sikuli import *
import unittest
import HTMLTestRunner
class channel1(unittest.TestCase):
def test_script1(self):
assert exists("1453186120180.png")
def test_script2(self):
assert exists("1453186901719.png")
class channel2(unittest.TestCase):
def test_script3(self):
assert exists("1453186120180.png")
def test_script4(self):
assert exists("1453186901719.png")
#channel2().test_script1()
#suite1 = unittest.TestLoader().loadTestsFromTestCase(_main_channel.channel1)
#ch1=channel1.test_script1()
#ch2=channel1.test_script2()
suite2= unittest.TestLoader().loadTestsFromTestCase(channel2)
#suite2 = unittest.TestLoader().loadTestsFromTestCase(obj2)
outfile = open("D:\\report.html", "wb") # path to report folder
#runner = HTMLTestRunner.HTMLTestRunner(stream=outfile, title=' Report Title', description='desc..' ).run(suite1)
runner = HTMLTestRunner.HTMLTestRunner(stream=outfile, title=' Report Title', description='desc..' ).run(suite1)
#runner = HTMLTestRunner.HTMLTestRunner(stream=outfile, title=' Report Title', description='desc..' ).run(suite2)
#runner.run(suite2)
Please help..

Categories