huskypo


Namehuskypo JSON
Version 1.3.0 PyPI version JSON
download
home_pagehttps://github.com/uujohnnyuu/huskyPO
SummaryUI Automation Page Objects design pattern.
upload_time2024-08-13 16:13:03
maintainerNone
docs_urlNone
authorJohnny
requires_pythonNone
licenseApache 2.0
keywords huskypo page object selenium appium automation
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # huskyPO

## Copyright
- Developer: Johnny Chou

## Overview
- huskyPO stands for husky Page Object, named 'husky' due to the author's fondness.
- Constructed using Python's data descriptors, it's a UI Page Object package.
- Enables developers to build Python Selenium/Appium UI automation scripts more easily and elegantly.

## Features
- Significantly simplifies and beautifully constructs Page objects and test scripts.
- Encapsulates and integrates commonly used methods of Selenium and Appium, with optimizations in certain functions.
- Uses explicit waiting as the core driving mechanism, and extends some official explicit waiting methods.

## Usage
- Build page objects simply and elegantly using the `Page` and `Element(s)` classes.
- Write test scripts simply and elegantly using the constructed Page objects.

## Example Code
1. First, construct a Page object in any Python file, each page recommended to be a separate Page class.
2. For example, in the my_page.py file:

```python
from huskypo import Page, Element, Elements
from huskypo import By
from huskypo import dynamic


class MyPage(Page):
    
    # Static elements, equivalent to the normal setup of page objects.
    # Similar to constructing Python instance objects.
    search_field = Element(By.NAME, 'q', remark='Search input box')
    search_results = Elements(By.TAG_NAME, 'h3', remark='All search results')
    search_result1 = Element(By.XPATH, '//h3[1]', remark='First search result')
    

    # Dynamic elements, suitable for special test scenarios 
    # where element locator info is decided at runtime during the test case.
    # Typically, dynamic elements make up a very small proportion; 
    # if the test environment is robust and stable, 
    # it's advisable to mostly use static elements.
    # Dynamic elements need to be written as instance methods of the Page class, 
    # and must be decorated with @dynamic to function properly.
    @dynamic
    def search_result(self, order: int = 1):
        return Element(By.XPATH, f'//h3[{order}]', remark=f'Search result no.{order}')

    @dynamic
    def keyword_results(self, keyword: str):
        return Elements(By.XPATH, f'//*[contains(text(), "{keyword}")]')


    # If you must set dynamic elements as properties, follow this order:
    @property
    @dynamic
    def keyword_results(self):
        return Elements(By.XPATH, f'//*[contains(text(), "{Keyword.text1}")]')


    # If you want to record information about dynamic elements and reuse it, 
    # it is recommended to revert to the official standard data descriptor dynamic assignment method.

    # 1. You must first create an object of a data descriptor, such as static_element.

    # 2. Create a function corresponding to static_element and assign a value to static_element,
    # This assignment method utilizes the "__set__" method of the data descriptor. 
    # The parameters given is the same as the way of initializing the "Element".

    # 3. When executing the testcase, first call dynamic_element. 
    # If the subsequent elements no longer change, you can directly use static_element for operations.

    static_element = Element()

    def dynamic_element(self, par) -> Element:
        # __set__ will get the tuple and assign it to Element to initialize static_element.
        # The logic of tuple is exactly the same as the method of placing parameters in an Element, 
        # such as (by, value, index, timeout, remark).
        # It also includes other configuration methods mentioned in the Element documentation, 
        # such as (by, value, remark), and so on.
        self.static_element = (By.XPATH, f'//*[contains(text(), "{par}")]', f'This is {par}')  
        return self.static_element

    def dynamic_element(self, par) -> Element:
        # If you want to clearly specify parameter names, you can also use a dictionary.
        self.static_element = {
            'by': By.XPATH, 
            'value': f'//*[contains(text(), "{par}")]', 
            'remark': f'This is {par}'}
        return self.static_element
```

3. After constructing the Page object in my_page.py, you can begin writing test cases.
4. For example, the content of the test_my_page.py file:
```python
from selenium import webdriver
from my_page import MyPage

class TestMyPage:
    
    driver = webdriver.Chrome()
    my_page = MyPage(driver)

    my_page.get("https://google.com")
    my_page.search_field.wait_present()
    my_page.save_screenshot("my/file/path/image.png")

    search_keyword = 'automation'
    my_page.search_field.send_keys(keyword, Keys.ENTER)
    my_page.search_results.wait_any_visible()
    my_page.save_screenshot("my/file/path/image.png")

    assert my_page.keyword_results(search_keyword).quantity > 1
    assert search_keyword in my_page.search_result1.text

    my_page.search_result1.click()
    ...

    driver.close()
```

5. By using the simple examples above, you can see how we can construct Page objects and write scripts intuitively and beautifully with Page, Element(s) classes, and using page.element.method() style.

6. All the element finding processes rely on explicit waiting methods, the core mainly being the official WebDriverWait and expected_conditions, this package extends the commonly used conditions of present, visible, clickable, selected in the Element(s) class and the driver methods and other page-related operations are encapsulated in the Page class.

## TODO
- Continuously monitor new features in Selenium 4.0 and Appium 2.0.
- Other optimizations.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/uujohnnyuu/huskyPO",
    "name": "huskypo",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "huskypo, page object, selenium, appium, automation",
    "author": "Johnny",
    "author_email": "johnny071531@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/a4/78/76b8e8517e2c120276435cc9a60f78eb3931fe03cd5066bda41e7eb2d470/huskypo-1.3.0.tar.gz",
    "platform": null,
    "description": "# huskyPO\n\n## Copyright\n- Developer: Johnny Chou\n\n## Overview\n- huskyPO stands for husky Page Object, named 'husky' due to the author's fondness.\n- Constructed using Python's data descriptors, it's a UI Page Object package.\n- Enables developers to build Python Selenium/Appium UI automation scripts more easily and elegantly.\n\n## Features\n- Significantly simplifies and beautifully constructs Page objects and test scripts.\n- Encapsulates and integrates commonly used methods of Selenium and Appium, with optimizations in certain functions.\n- Uses explicit waiting as the core driving mechanism, and extends some official explicit waiting methods.\n\n## Usage\n- Build page objects simply and elegantly using the `Page` and `Element(s)` classes.\n- Write test scripts simply and elegantly using the constructed Page objects.\n\n## Example Code\n1. First, construct a Page object in any Python file, each page recommended to be a separate Page class.\n2. For example, in the my_page.py file:\n\n```python\nfrom huskypo import Page, Element, Elements\nfrom huskypo import By\nfrom huskypo import dynamic\n\n\nclass MyPage(Page):\n    \n    # Static elements, equivalent to the normal setup of page objects.\n    # Similar to constructing Python instance objects.\n    search_field = Element(By.NAME, 'q', remark='Search input box')\n    search_results = Elements(By.TAG_NAME, 'h3', remark='All search results')\n    search_result1 = Element(By.XPATH, '//h3[1]', remark='First search result')\n    \n\n    # Dynamic elements, suitable for special test scenarios \n    # where element locator info is decided at runtime during the test case.\n    # Typically, dynamic elements make up a very small proportion; \n    # if the test environment is robust and stable, \n    # it's advisable to mostly use static elements.\n    # Dynamic elements need to be written as instance methods of the Page class, \n    # and must be decorated with @dynamic to function properly.\n    @dynamic\n    def search_result(self, order: int = 1):\n        return Element(By.XPATH, f'//h3[{order}]', remark=f'Search result no.{order}')\n\n    @dynamic\n    def keyword_results(self, keyword: str):\n        return Elements(By.XPATH, f'//*[contains(text(), \"{keyword}\")]')\n\n\n    # If you must set dynamic elements as properties, follow this order:\n    @property\n    @dynamic\n    def keyword_results(self):\n        return Elements(By.XPATH, f'//*[contains(text(), \"{Keyword.text1}\")]')\n\n\n    # If you want to record information about dynamic elements and reuse it, \n    # it is recommended to revert to the official standard data descriptor dynamic assignment method.\n\n    # 1. You must first create an object of a data descriptor, such as static_element.\n\n    # 2. Create a function corresponding to static_element and assign a value to static_element,\n    # This assignment method utilizes the \"__set__\" method of the data descriptor. \n    # The parameters given is the same as the way of initializing the \"Element\".\n\n    # 3. When executing the testcase, first call dynamic_element. \n    # If the subsequent elements no longer change, you can directly use static_element for operations.\n\n    static_element = Element()\n\n    def dynamic_element(self, par) -> Element:\n        # __set__ will get the tuple and assign it to Element to initialize static_element.\n        # The logic of tuple is exactly the same as the method of placing parameters in an Element, \n        # such as (by, value, index, timeout, remark).\n        # It also includes other configuration methods mentioned in the Element documentation, \n        # such as (by, value, remark), and so on.\n        self.static_element = (By.XPATH, f'//*[contains(text(), \"{par}\")]', f'This is {par}')  \n        return self.static_element\n\n    def dynamic_element(self, par) -> Element:\n        # If you want to clearly specify parameter names, you can also use a dictionary.\n        self.static_element = {\n            'by': By.XPATH, \n            'value': f'//*[contains(text(), \"{par}\")]', \n            'remark': f'This is {par}'}\n        return self.static_element\n```\n\n3. After constructing the Page object in my_page.py, you can begin writing test cases.\n4. For example, the content of the test_my_page.py file:\n```python\nfrom selenium import webdriver\nfrom my_page import MyPage\n\nclass TestMyPage:\n    \n    driver = webdriver.Chrome()\n    my_page = MyPage(driver)\n\n    my_page.get(\"https://google.com\")\n    my_page.search_field.wait_present()\n    my_page.save_screenshot(\"my/file/path/image.png\")\n\n    search_keyword = 'automation'\n    my_page.search_field.send_keys(keyword, Keys.ENTER)\n    my_page.search_results.wait_any_visible()\n    my_page.save_screenshot(\"my/file/path/image.png\")\n\n    assert my_page.keyword_results(search_keyword).quantity > 1\n    assert search_keyword in my_page.search_result1.text\n\n    my_page.search_result1.click()\n    ...\n\n    driver.close()\n```\n\n5. By using the simple examples above, you can see how we can construct Page objects and write scripts intuitively and beautifully with Page, Element(s) classes, and using page.element.method() style.\n\n6. All the element finding processes rely on explicit waiting methods, the core mainly being the official WebDriverWait and expected_conditions, this package extends the commonly used conditions of present, visible, clickable, selected in the Element(s) class and the driver methods and other page-related operations are encapsulated in the Page class.\n\n## TODO\n- Continuously monitor new features in Selenium 4.0 and Appium 2.0.\n- Other optimizations.\n",
    "bugtrack_url": null,
    "license": "Apache 2.0",
    "summary": "UI Automation Page Objects design pattern.",
    "version": "1.3.0",
    "project_urls": {
        "Homepage": "https://github.com/uujohnnyuu/huskyPO"
    },
    "split_keywords": [
        "huskypo",
        " page object",
        " selenium",
        " appium",
        " automation"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "1931b4dd9987a1ed9c34b2180660b32433477202c3cc5b0f16bf13cc02d08f70",
                "md5": "f7fa82d197bd34f0a95ff8136af133cd",
                "sha256": "c7d8c0022cae5882b5ba1bf0d132a2c5fcb9823199c91c98fe75fa8ecab6c4a5"
            },
            "downloads": -1,
            "filename": "huskypo-1.3.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "f7fa82d197bd34f0a95ff8136af133cd",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 55038,
            "upload_time": "2024-08-13T16:13:01",
            "upload_time_iso_8601": "2024-08-13T16:13:01.273052Z",
            "url": "https://files.pythonhosted.org/packages/19/31/b4dd9987a1ed9c34b2180660b32433477202c3cc5b0f16bf13cc02d08f70/huskypo-1.3.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a47876b8e8517e2c120276435cc9a60f78eb3931fe03cd5066bda41e7eb2d470",
                "md5": "4daeca0bbe43fae124d06bff08072285",
                "sha256": "3fcfa27673d99dc9b4b975efb662e48b87daa7ac3e36d2b2f990a84900dc3d7b"
            },
            "downloads": -1,
            "filename": "huskypo-1.3.0.tar.gz",
            "has_sig": false,
            "md5_digest": "4daeca0bbe43fae124d06bff08072285",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 52778,
            "upload_time": "2024-08-13T16:13:03",
            "upload_time_iso_8601": "2024-08-13T16:13:03.970537Z",
            "url": "https://files.pythonhosted.org/packages/a4/78/76b8e8517e2c120276435cc9a60f78eb3931fe03cd5066bda41e7eb2d470/huskypo-1.3.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-08-13 16:13:03",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "uujohnnyuu",
    "github_project": "huskyPO",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "huskypo"
}
        
Elapsed time: 0.29173s