Best Python code snippet using robotframework-pageobjects_python
test_functional.py
Source:test_functional.py  
1import json2import os3import re4import unittest5import requests6import xml.etree.ElementTree as ET7from nose.tools import raises8from robotpageobjects import Page, exceptions9from scenarios.po.result_component import ResultPage, ResultPageWithDOMStrategyLocator, HomePage, \10    HomePageWithDOMAdvancedToggler, TwoComponentsPage, ParaComponent, TwoComponentsSubPage11from scenarios.po.loggingpage import LoggingPage12from basetestcase import BaseTestCase13class SmokeTestCase(BaseTestCase):14    """15    Tests for basic options and option handling.16    For tests outside of Robot, individual environment variables17    in the form of "$PO_" (eg. $PO_BROWSER) set options.18    A variable of $PO_VAR_FILE can be set to a path to a Python19    module that can set variables as well. Individual20    environment variables override those set in the variable file.21    For tests within the Robot context the behavior follows22    standard Robot Framework..variables can be set on the23    command-line with --variable (eg. --variable=browser=firefox, which24    override the variables set in a variable file, set with --variablefile=25    The BaseTestCase setUp removes all PO environment variables.26    tearDown restores them. It also removes po_log file in27    setUp and tearDown and screenshots in setUp28    This assures that at the beginning of each test there are no29    PO_ environment variables set and that we are running with30    default options. The tests are then free to set environment variables or31    write variable files as needed.32    This test case tests browser option, but in effect also tests option handling, assuming33    that options are gotten internally using the optionhandler.OptionHandler class.34    """35    def test_unittest_rel_uri_set(self):36        self.set_baseurl_env()37        run = self.run_scenario("test_rel_uri_attr.py")38        self.assert_run(run, search_output="OK", expected_browser="phantomjs")39    def test_robot_rel_uri_set(self):40        run = self.run_scenario("test_rel_uri_attr.robot", variable="baseurl:%s" % self.base_file_url)41        self.assert_run(run, search_output="PASS", expected_browser="phantomjs")42    def test_robot_no_name_attr_should_use_underscored_class_name_to_namespaced_keyword(self):43        run = self.run_scenario("test_rel_uri_attr_no_name_attr.robot", variable="baseurl:%s" % self.base_file_url)44        self.assert_run(run, search_output="PASS", expected_browser="phantomjs")45    def test_unittest_uri_template(self):46        # This tests open() as well as uri_template.47        self.set_baseurl_env()48        run = self.run_scenario("test_template_passed.py")49        self.assert_run(run, expected_returncode=0, search_output="OK")50    def test_robot_uri_template(self):51        # This tests open() as well as uri_template.52        run = self.run_scenario("test_template_passed.robot", variable="baseurl:%s" % self.base_file_url)53        self.assert_run(run, expected_returncode=0, search_output="PASS")54    def test_no_baseurl_gives_readable_error_in_robot(self):55        run = self.run_scenario("test_template_passed.robot")56        self.assert_run(run, expected_returncode=1, search_output="must set a baseurl")57    def stack_trace_in_robot_log(self):58        self.set_baseurl_env()59        run = self.run_scenario("test_stack_trace.robot", v="baseurl:%s" % self.base_file_url, L="TRACE")60        self.assert_run(run, expected_returncode=1, search_output_xml="in raise_division_by_zero")61    def test_no_screenshot_attempt_on_initializing_page_with_component(self):62        self.set_baseurl_env()63        run = self.run_scenario("test_page_with_component.robot")64        self.assert_run(run, expected_returncode=0, search_output="PASS",65                        not_in_output="Capture Page Screenshot")66class SauceTestCase(BaseTestCase):67    """68    Sauce exception tests are in the unit tests, not the69    functional tests.70    """71    def get_job_data(self, sid):72        username, apikey = self.get_sauce_creds()73        rest_url = "https://%s:%s@saucelabs.com/rest/v1/%s/jobs/%s" % (username, apikey, username, sid)74        resp = requests.get(rest_url)75        return json.loads(resp.content)76    def get_sid_from_log(self, is_robot=False):77        log_path = self.get_log_path(is_robot)78        try:79            f = open(log_path)80            content = f.read()81            try:82                return re.search(r"session ID: (.{32})", content).group(1)83            except (AttributeError, IndexError):84                raise Exception("Couldn't get the session ID from the log %s" % log_path)85        except OSError:86            raise "Couldn't find a log file at %s" % log_path87        except IOError:88            raise Exception("Couldn't open log file %s" % log_path)89        finally:90            f.close()91    @unittest.skipUnless(BaseTestCase.are_sauce_creds_set_for_testing(),92                         "Must set 'SAUCE_USERNAME' and 'SAUCE_APIKEY' ("93                         "not PO_SAUCE."94                         ".) "95                         "as an env "96                         "variables to run this test")97    def test_sauce_unittest(self):98        self.assertFalse(os.path.exists(self.get_log_path()))99        run = self.run_scenario("test_sauce.py")100        job_data = self.get_job_data(self.get_sid_from_log())101        # Just check an arbitrary entry in the job data returned from sauce.102        self.assertEquals(job_data["browser"], "firefox", "The job ran in Sauce")103        # We expect this to fail, because the test makes a purposely false assertion104        # to test that we can assert against things going on in Sauce.105        self.assert_run(run, expected_returncode=1, search_output="Title should have been 'foo' but was 'Home - "106                                                                  "PubMed - NCBI")107    @unittest.skipUnless(BaseTestCase.are_sauce_creds_set_for_testing(),108                         "Must set 'SAUCE_USERNAME' and 'SAUCE_APIKEY' ("109                         "not "110                         "PO_SAUCE..) "111                         "as an env "112                         "variables to run this test")113    def test_sauce_robot(self):114        self.assertFalse(os.path.exists(self.get_log_path(is_robot=True)))115        run = self.run_scenario("test_sauce.robot", variablefile=os.path.join(self.test_dir, "sauce_vars.py"))116        job_data = self.get_job_data(self.get_sid_from_log(is_robot=True))117        # Just check an arbitrary entry in the job data returned from sauce.118        self.assertEquals(job_data["browser"], "firefox", "The job ran in Sauce")119        self.assert_run(run, expected_returncode=1, search_output="Title should have been 'foo' but was 'Home - "120                                                                  "PubMed - NCBI")121class ActionsTestCase(BaseTestCase):122    """123    DCLT-768: TODO124    @unittest.skip("NOT IMPLEMENTED YET. ")125    def test_unittest_screenshot_on_failure(self):126        self.assert_screen_shots(0)127        self.run_scenario("test_fail.py")128        self.assert_screen_shots(1)129    """130    def test_robot_screen_shot_on_page_object_keyword_failure(self):131        self.assert_screen_shots(0)132        self.run_scenario("test_fail.robot", variable="baseurl:%s" % self.base_file_url)133        self.assert_screen_shots(1)134    def test_robot_screen_shot_on_se2lib_keyword_failure(self):135        self.assert_screen_shots(0)136        self.run_scenario("test_fail_se2lib_keyword.robot", variable="baseurl:%s" % self.base_file_url)137        self.assert_screen_shots(1)138    def test_manual_screenshot_outside_robot(self):139        self.assert_screen_shots(0)140        self.set_baseurl_env()141        run = self.run_scenario("test_manual_screen_shot.py")142        self.assert_run(run, expected_returncode=0, search_output="OK")143        self.assert_screen_shots(1)144    def test_manual_screenshot_robot(self):145        self.assert_screen_shots(0)146        run = self.run_scenario("test_manual_screen_shot.robot", variable="baseurl:%s" % self.base_file_url)147        self.assert_run(run, expected_returncode=0, search_output="PASS")148        self.assert_screen_shots(1)149    def test_go_to_robot(self):150        run = self.run_scenario("test_go_to.robot", variable="baseurl:%s" % self.base_file_url)151        self.assert_run(run, expected_returncode=0, search_output="PASS")152    def test_go_to_outside_robot(self):153        self.set_baseurl_env()154        run = self.run_scenario("test_go_to.py")155        self.assert_run(run, expected_returncode=0, search_output="OK")156    def test_is_visible(self):157        self.set_baseurl_env()158        run = self.run_scenario("test_is_visible.py")159        self.assert_run(run, expected_returncode=0, search_output="OK")160    def test_location_should_be_for_relative_path(self):161        run = self.run_scenario("test_location_should_be_for_relative_path.py")162        self.assert_run(run, expected_returncode=0, search_output="OK")163    def test_location_should_be_for_absolute_path(self):164        run = self.run_scenario("test_location_should_be_for_absolute_path.py")165        self.assert_run(run, expected_returncode=0, search_output="OK")166class SelectorsTestCase(BaseTestCase):167    def setUp(self):168        super(SelectorsTestCase, self).setUp()169        self.set_baseurl_env()170    def test_s2l_keyword_with_selector(self):171        run = self.run_scenario("test_s2l_keyword_with_selector.robot", variable="baseurl:%s" % self.base_file_url)172        self.assert_run(run, expected_returncode=0, search_output="PASS")173    def test_find_elements_with_selector(self):174        run = self.run_scenario("test_find_elements_with_selector.py")175        self.assert_run(run, expected_returncode=0, search_output="OK")176    def test_bad_selector_raises_exception(self):177        run = self.run_scenario("test_bad_selector.py")178        self.assert_run(run, expected_returncode=0, search_output="OK")179    def test_no_selector_raises_exception(self):180        run = self.run_scenario("test_no_selector.py")181        self.assert_run(run, expected_returncode=0, search_output="OK")182    def test_selector_template(self):183        run = self.run_scenario("test_templated_selector.py")184        self.assert_run(run, expected_returncode=0, search_output="OK")185    def test_selector_self_ref(self):186        run = self.run_scenario("test_selector_self_ref.py")187        self.assert_run(run, expected_returncode=0, search_output="OK")188#    def test_no_robot_action_failing_should_not_warn_about_screenshot(self):189#        run = self.run_scenario("test_fail.py")190#        self.assertFalse("warn" in run.output.lower(), "No warning should be issued when a method fails outside "191#                                                       "robot")192#193    def robot_importing_se2lib_after_page_object_should_work(self):194        # This run is duplicated, but it shows that SE2Lib library imported195        # with page objects works.196        run = self.run_scenario("test_template_passed.robot")197        self.assert_run(run, expected_returncode=0, search_output="PASS")198    def robot_importing_se2lib_before_page_object_should_work(self):199        run = self.run_scenario("test_se2lib_imported_before_po.robot")200        self.assert_run(run, expected_returncode=0, search_output="PASS")201    def test_selector_with_se2lib_keyword(self):202        self.set_baseurl_env()203        run = self.run_scenario("test_selector_with_se2lib_keyword.robot")204        self.assert_run(run, expected_returncode=0, search_output="PASS")205class ComponentTestCase(BaseTestCase):206    def setUp(self):207        super(ComponentTestCase, self).setUp()208        self.set_baseurl_env()209        self.result_page_with_str_locator = ResultPage()210        self.result_page_with_dom_strategy_locator = ResultPageWithDOMStrategyLocator()211        self.homepage = HomePage()212        self.homepage_with_dom_toggler = HomePageWithDOMAdvancedToggler()213        self.two_comp_page = TwoComponentsPage()214    def test_selenium_implicit_wait_not_reset_within_component(self):215        self.result_page_with_str_locator.open()216        self.assertEquals(217            self.result_page_with_str_locator.get_selenium_implicit_wait(),218            "10 seconds"219        )220        self.assertEquals(221            self.result_page_with_str_locator.result.get_selenium_implicit_wait(),222            "10 seconds"223        )224    def test_get_instance_and_instances(self):225        # Test get_instance and get_instances in same test. get_instance()226        # get_instances() are called by the component admin class to set227        # component instances on the page object.228        # In the same component admin, get_instance and get_instances229        # are called so we can access the result, or results object(s).230        # You'd use get_instance() if you expected only one231        # instance, and get_instances() if you expected > 1.232        # Normally, of course, in the admin class, you'd call only233        # one of these, not both.234        self.result_page_with_str_locator.open()235        self.assertNotEquals(type(self.result_page_with_str_locator.result), list)236        # Should get the first result since we are accessing "result", not "results".237        self.assertEquals(self.result_page_with_str_locator.result.price, "$14.00")238        # Now access "results" in the plural.239        self.assertEquals(len(self.result_page_with_str_locator.results), 3)240        self.assertEquals(self.result_page_with_str_locator.results[0].price, "$14.00")241    def test_locator_as_dom(self):242        self.result_page_with_dom_strategy_locator.open()243        results = self.result_page_with_dom_strategy_locator.results244        # The locator uses DOM strategy to get the nodes via a call245        # to execute_javascript() and limits to 2 results, just246        # to make sure we are testing the right thing.247        self.assertEquals(len(results), 2)248        # Check that the result object works.249        self.assertEquals(results[0].price, "$14.00")250    def test_component_inside_component(self):251        # A component should be able to contain other components. You'd access252        # sub component by accessing the sub component name as a property on the253        # parent component.254        # These tests import the page classes directly, instead of going255        # through run_scenario(), which is inconsistent with the rest of the256        # Python tests. We do this because it's just clearer and easier to257        # debug. We should probably clean up the other tests to do the same.258        # See QAR-47882.259        # We don't see the need for writing these tests in both Robot and Python260        # because we already feel confident that page objects perform the same261        # in both contexts, as the other tests show.262        self.homepage.open()263        search_component = self.homepage.search264        self.homepage.textfield_value_should_be("id=q", "", "The search component's input doesn't start blank")265        search_component.set_search_term("foo")266        self.homepage.textfield_value_should_be("id=q", "foo", "Search component can't set a search value")267        # Access a sub component268        advanced_option_toggler_component = search_component.advancedoptiontoggler269        self.homepage.element_should_not_be_visible("id=advanced-search-content")270        advanced_option_toggler_component.open()271        self.homepage.element_should_be_visible("id=advanced-search-content")272    def test_component_inside_component_with_dom(self):273        # When you have a component inside another component, the parent should be274        # able to search for the child using the child's locator. The child's locator275        # should be interpreted with reference to the parent's reference_webelement.276        self.homepage_with_dom_toggler.open()277        search_component = self.homepage_with_dom_toggler.searchcomponentwithdomadvancedtoggler278        advanced_option_toggler_component = search_component.advancedoptiontoggler279    def test_use_selectors_to_get_non_child_element(self):280        self.homepage.open()281        toggler = self.homepage.search.advancedoptiontoggler282        toggler.open()283        self.assertEquals(toggler.advanced_text, "These are advanced options")284    def test_page_inherits_from_multiple_components(self):285        paras = self.two_comp_page.open().paras286        self.assertTrue(len(paras) > 1, "Locator for body component is being used, so not finding "287                                        "more than one paragraph component on page")288    def test_calling_log_from_component(self):289        self.homepage.open()290        attr_err_raised = False291        try:292            self.homepage.get_some_property()293        except AttributeError:294            attr_err_raised = True295        self.assertFalse(attr_err_raised, "AttributeError raised when trying to call log() from a component")296    def test_page_inherits_super_pages_components(self):297        self.two_comp_page = TwoComponentsSubPage().open()298        try:299            body = self.two_comp_page.body300            found = True301        except AttributeError:302            found = False303        self.assertTrue(found, "body attribute should exist when inheriting from super class")304    def test_page_overrides_super_pages_components(self):305        self.two_comp_page = TwoComponentsSubPage().open()306        paras = self.two_comp_page.paras307        self.assertEqual(len(paras), 1, "Overridden locator for paras should return just the last one")308    def test_page_override_without_override_class_raises_warning(self):309        run = self.run_scenario("test_page_override_without_override_class.py", env={"PYTHONPATH": self.po_dir})310        self.assert_run(run, expected_returncode=0, search_output="KeyOverrideWarning")311    def tearDown(self):312        super(ComponentTestCase, self).tearDown()313        self.result_page_with_str_locator.close()314        self.result_page_with_dom_strategy_locator.close()315        self.homepage.close()316        self.two_comp_page.close()317class KeywordsTestCase(BaseTestCase):318    def test_dont_have_to_specify_page_name_in_keyword_when_2_page_objects_inherit_it(self):319        run = self.run_scenario("test_dont_have_to_specify_page_name_in_keyword_when_2_page_objects_inherit_it.robot",320                                variable="baseurl:%s" % self.base_file_url)321        self.assert_run(run, expected_returncode=0, search_output="PASS")322    def test_dont_have_to_specify_page_name_for_keyword_when_2_page_objects_define_it(self):323        run = self.run_scenario("test_dont_have_to_specify_page_name_for_keyword_when_2_page_objects_define_it.robot",324                                variable="baseurl:%s" % self.base_file_url)325        self.assert_run(run, expected_returncode=0, search_output="PASS")326    def test_dont_have_to_specify_page_name_when_extending_se2lib_keyword(self):327        run = self.run_scenario("test_dont_have_to_specify_page_name_when_extending_se2lib_keyword.robot",328                                variable="baseurl:%s" % self.base_file_url)329        self.assert_run(run, expected_returncode=0, search_output="PASS")330    def test_keyword_does_not_return_page_object(self):331        run = self.run_scenario("test_does_not_return.robot", variable="baseurl:%s" % self.base_file_url)332        self.assert_run(run, expected_returncode=1,333                        search_output="You must return either a page object or an appropriate value from the page object method")334    def test_can_alias_without_page_name(self):335        run = self.run_scenario("test_can_call_aliased_method_without_page_name.robot",336                                variable="baseurl:%s" % self.base_file_url)337        self.assert_run(run, expected_returncode=0, search_output="PASS")338    def test_can_alias_with_page_name(self):339        run = self.run_scenario("test_can_call_aliased_method_with_page_name.robot",340                                variable="baseurl:%s" % self.base_file_url)341        self.assert_run(run, expected_returncode=0, search_output="PASS")342    def test_can_call_unaliased_with_page_name(self):343        run = self.run_scenario("test_can_call_unaliased_method_with_page_name.robot",344                                variable="baseurl:%s" % self.base_file_url)345        self.assert_run(run, expected_returncode=0, search_output="PASS")346    def test_negative_index_in_table_keywords(self):347        run = self.run_scenario("test_negative_index_in_table_keywords.robot",348                                variable="baseurl:%s" % self.base_file_url)349        self.assert_run(run, expected_returncode=0, search_output="PASS")350    def test_se2lib_keywords_are_still_available_if_both_se2lib_and_po_are_imported(self):351        run = self.run_scenario("test_se2lib_called_before_po.robot",352                                variable="baseurl:%s" % self.base_file_url)353        self.assert_run(run, expected_returncode=0, search_output="PASS")354class WaitingTestCase(BaseTestCase):355    def test_implicit_wait_default_works(self):356        self.set_baseurl_env()357        run = self.run_scenario("test_implicit_se_wait.py")358        self.assert_run(run, expected_returncode=0, search_output="OK")359    def test_implicit_wait_fails_with_option_set_to_1(self):360        self.set_baseurl_env()361        run = self.run_scenario("test_implicit_se_wait.py", env={"PO_SELENIUM_IMPLICIT_WAIT": "1"})362        self.assert_run(run, expected_returncode=1, search_output="FAIL")363    def test_implicit_wait_can_be_set_to_0(self):364        self.set_baseurl_env()365        run = self.run_scenario("test_implicit_se_wait_0.py", env={"PO_SELENIUM_IMPLICIT_WAIT": "0"})366        self.assert_run(run, expected_returncode=0, search_output="OK")367    def test_can_set_wait_on_call_to_find_element_and_find_elements(self):368        self.set_baseurl_env()369        run = self.run_scenario("test_pass_explicit_wait_to_find_element.py")370        self.assert_run(run, expected_returncode=0, search_output="OK")371    def test_wait_till_element_disappears(self):372        self.set_baseurl_env()373        run = self.run_scenario("test_wait_until_not_visible.py")374        self.assert_run(run, expected_returncode=0)375class LoggingTestCase(BaseTestCase):376    """377    # Tests that assert whether or not messages are logged depending on the log level378    # logged in relation to the log level threshold.379    # For example, given these logging levels (from severe to less severe):380    CRITICAL381    ERROR382    WARNING383    INFO384    DEBUG385    NOTSET386    Let's say that the threshold is set at INFO, and we log "above" the threshold at387    CRITICAL by calling388    self.log("hello world", "CRITICAL")389    We expect that this message would get logged.390    If, on the other hand, we logged below391    the threshold at "DEBUG", we'd expect the message to not get logged.392    """393    def test_log_below_threshold_should_log_to_stdout_but_not_to_file_robot(self):394        # Unless we specify is_console=False, we always log to stdout in Robot395        run = self.run_scenario("test_log_below_threshold.robot")396        self.assert_run(run, expected_returncode=0, search_output="DEBUG - Logging Page - hello world",397                        not_in_log="hello world")398    def test_log_below_threshold_should_not_log_to_stdout_and_not_to_file_if_is_console_false_robot(self):399        # Unless we specify is_console=False, we always log to stdout in Robot400        run = self.run_scenario("test_log_below_threshold_is_console_false.robot")401        self.assert_run(run, expected_returncode=0, not_in_output="hello world", not_in_log="hello world")402    def test_log_below_threshold_should_not_log_to_stdout_and_file_python(self):403        run = self.run_scenario("test_log_below_threshold.py")404        self.assert_run(run, expected_returncode=0, not_in_output="hello world", not_in_log="hello world")405    def test_log_below_threshold_is_console_false_should_not_log_to_file_and_not_to_console_python(self):406        run = self.run_scenario("test_log_below_threshold_is_console_false.py")407        self.assert_run(run, expected_returncode=0, not_in_output="hello world", not_in_log="hello world")408    def test_log_above_threshold_should_log_to_stdout_and_file_robot(self):409        run = self.run_scenario("test_log_above_threshold.robot")410        self.assert_run(run, expected_returncode=0, search_output="WARNING - Logging Page - hello world",411                        search_log="hello world")412    def test_log_at_threshold_should_log_to_stdout_and_file_robot(self):413        run = self.run_scenario("test_log_at_threshold.robot")414        self.assert_run(run, expected_returncode=0, search_output="INFO - Logging Page - hello world",415                        search_log="hello world")416    def test_log_at_or_above_threshold_should_log_to_stdout_and_file_python(self):417        run = self.run_scenario("test_log_at_threshold.py")418        self.assert_run(run, expected_returncode=0, search_output="INFO - Logging Page - hello world",419                        search_log="INFO - Logging Page - hello world")420    def test_log_at_or_above_threshold_console_false_should_log_to_file_but_not_stdout_python(self):421        run = self.run_scenario("test_log_at_threshold_is_console_false.py")422        self.assert_run(run, expected_returncode=0, not_in_output="hello world", search_log="INFO - Logging Page - hello world")423    def test_one_instance_of_file_logger(self):424        class MyPage(Page):425            pass426        path_to_log = os.path.join(os.getcwd(), "po_log.txt")427        # Clear the log in case any other test has written to it. Set up deals with428        # po_log.txt at tests/scenarios directory.429        f = open(path_to_log, "w")430        f.write("")431        f.close()432        # Now log from two different page objects433        Page().log("hello", is_console=False)434        MyPage().log("world", is_console=False)435        f = open(path_to_log)436        log_content =  f.read()437        try:438            # We expect to see two lines in the log, logged in order from Page to My Page.439            self.assertRegexpMatches(log_content, r".+ - INFO - Page - hello\n.+ - INFO - My Page - world$")440            # 3 lines are really 2 lines because of final line break441            self.assertEquals(len(log_content.split("\n")), 3)442        finally:443            f.close()444            os.unlink(path_to_log)445    def test_log_non_string(self):446        try:447            Page().log([1,2,3], is_console=False)448        except TypeError:449            self.fail("Logging a non string causes a TypeError")450    @raises(ValueError)451    def test_log_at_invalid_level_python(self):452        LoggingPage().log_invalid()453class LibdocTestCase(BaseTestCase):454    def test_gen_doc(self):455        # generate libdoc xml456        outxml = 'libdoc.xml'457        run = self.run_program("python", ".", "robotpageobjects.page.Page %s" % outxml, **{"m": "robot.libdoc"})458        self.assert_run(run, expected_returncode=0, search_output=outxml)459        root = ET.parse(outxml).getroot()460        kwentry = root.findall(".//kw[@name='Log']")461        if len(kwentry) == 0:462            raise AssertionError('Expected to find entry for "Log" in %s' % outxml)463        kwentry = kwentry[0]464        kwargs = kwentry.findall('./arguments/arg')465        if len(kwargs) != 3:466            raise AssertionError('Expected to find 3 arguments for "Log" in %s' % outxml)467        doc = kwentry.findall('./doc')[0]468        if 'DEBUG' not in doc.text:469            raise AssertionError('Expected to find "DEBUG" in docmentation for "Log" in %s' % outxml)470class MultipleSuiteLibraryImport(BaseTestCase):471    def test_libraries_stay_imported(self):472        self.set_baseurl_env()473        run = self.run_scenario("test_s2l_imported_multiple_a.robot test_s2l_imported_multiple_b.robot")...stacktracepage.py
Source:stacktracepage.py  
1from robotpageobjects import Page2class StackTracePage(Page):3    uri = "site/index.html"4    def raise_division_by_zero(self):5        1/0...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
