Ziwdigforbugs
Ziwdigforbugs

Reputation: 1214

Robot Framework not recognizing some class keywords

I am creating a RobotFramework library with three different classes. I am able to use the first class keywords, however I am not able to use the two remaining classes keywords. As per RF documentation I tried to use import as follow LibraryName.className And I am also setting python Path to my personal library’s folder. However when running tests only first class keyword are recognised. I have tried to change the name of my first class to a different name then my lib file and import each class separately but that did not work for the three class’s keywords.

Here is my Lib code :

from robotpageobjects import Page, robot_alias
from robot.utils import asserts


class HomePage(Page):
    """ Models WeekendDesk home page at:
        HOST:weekendesk.fr/"""

    name="Home"
    # This is Then Keyword for Weekendesk Home Page.

    # This page is found at baseurl"
    uri = ""

    # inheritable dictionary mapping human-readable names
    # to Selenium2Library locators. You can then pass in the
    # keys to Selenium2Library actions instead of the locator
    # strings.

    selectors = {
        "destination": "id=concatField",
        "search button": "id=searchButton",
        "arrival date": "id=spArrival",
        "departure date": "id=spDeparture",

    }

    # Use robot_alias and the "__name__" token to customize
    # where to insert the optional page object name
    # when calling this keyword. Without the "__name__"
    # token this method would map to either "Type In Search Box",
    # or "Type In Search Box WDHomePage". Using "__name__" we can call
    # "Type in Home Search Box  foo".
    @robot_alias("type_in__name__search_box")
    def type_in_search_box(self, txt):
        self.input_text("destination", txt)

        # We always return something from a page object,
        # even if it's the same page object instance we are
        # currently on.
        return self

    @robot_alias("type_in__name__arrival_box")
    def type_in_arrival_box(self, txt):
        self.input_text("arrival date", txt)

        # We always return something from a page object,
        # even if it's the same page object instance we are
        # currently on.
        return self

    @robot_alias("type_in__name__departure_box")
    def type_in_departure_box(self, txt):
        self.input_text("departure date", txt)

        # We always return something from a page object,
        # even if it's the same page object instance we are
        # currently on.
        return self

    @robot_alias("click__name__search_button")
    def click_search_button(self):
        self.click_link("search button")
        return SerpPage()

    @robot_alias("search_weekends_for")
    def search_for(self, concatField,spArrival,spDeparture):
        self.type_in_search_box(concatField)
        self.type_in_arrival_box(spArrival)
        self.type_in_departure_box(spDeparture)
        return self.click_search_button()


class SerpPage(Page):

    """Models a Serp search result page. For example:
    http://www.weekendesk.fr/sejour/DTE6_070815RGN1_iPLC2_3iNGH1_5VRS1_9  /weekend-en-PACA """
    # The URI for the SERP page does not have a template to follow

    uri = ""
    Name= "Serp"

    # This is a "selector template". We are parameterizing the
    # nth result in this xpath. We call this from click_result, below.
    selectors = {
        "nth result link": "div.searchResult:nth-child(1) > div:nth-child(1) > h2:nth-child(1) > a:nth-child(1)"

    }

    @robot_alias("click_result_on__name__")
    def click_result(self, i):

        # For selector templates, we need to resolve the selector to the
        # locator first, before finding or acting on the element.
        locator = self.resolve_selector("nth result link", n=int(i))
        self.click_link(locator)
        return ProductPage()

class ProductPage(Page):

    uri = ""
    Name="Product"

    @robot_alias("__name__body_should_contain")
    def body_should_contain(self, str, ignore_case=True):
        ref_str = str.lower() if ignore_case else str
        ref_str = ref_str.encode("utf-8")
        body_txt = self.get_text("css=body").encode("utf-8").lower()
        asserts.assert_true(ref_str in body_txt, "body text does not contain %s" %ref_str)
        return self

My Lib file name is HomePage.py

Thanks

Upvotes: 2

Views: 3238

Answers (1)

Raceyman
Raceyman

Reputation: 1354

What you're asking to do should be possible, however, without seeing your robot test suite, it's not really clear what you're actually doing. For example, if your library file is on the PYTHONPATH, you can import the classes individually. For example, if this was your library file, I called mine LibTest.py:

from robot.api import logger

class LibTest:
    def libtest_1(self):
        logger.warn("In LibTest")

class OtherTest:
    def othertest_1(self):
        logger.warn("In OtherTest")

class OneMoreTest:
    def onemoretest_1(self):
        logger.warn("In OneMoreTest")

Then in your Test Suite, you can load the classes individually:

*** Settings ***
Library           LibTest.LibTest
Library           LibTest.OtherTest
Library           LibTest.OneMoreTest
 
*** Test Cases ***
sometest
    Log    Test Start
    libtest_1
    othertest_1
    onemoretest_1

This example works on my environment: Python 2.7.6 with Robot Framework 2.8.7. Here is the console I output I get:

20150831 12:48:49.449 : INFO : Test Start

20150831 12:48:49.450 : WARN : In LibTest

20150831 12:48:49.450 : WARN : In OtherTest

20150831 12:48:49.451 : WARN : In OneMoreTest

I think Robot, though, is really trying to encourage you to keep your library classes in separate files - as it's a little bit easier to deal with, i.e., you don't need to put them on the PYTHONPATH.

Upvotes: 2

Related Questions