Skip to content

Commit

Permalink
Selector 'link:' and 'partial link:' are now optional if element type…
Browse files Browse the repository at this point in the history
… is defined

- Update README
- Add test_devpost.txt
  • Loading branch information
roniemartinez committed Aug 31, 2019
1 parent 513a856 commit b63b2d7
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 36 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,14 @@

## Unreleased

## 0.5.3 - 2019-08-31
### Changed
- Selector 'link:' and 'partial link:' are now optional if element type is defined
- Update README

### Added
- Add test_devpost.txt

## 0.5.2 - 2019-08-30
### Changed
- Move to GPLv3
Expand Down
25 changes: 15 additions & 10 deletions README.md
Expand Up @@ -2,32 +2,36 @@

> NOTICE: Human Framework is still on the **Proof-of-Concept** stage
> CONTRIBUTE! I am releasing Human Framework under GPLv3 which makes it open source and free. Contribute by:
> CONTRIBUTE! I am releasing Human Framework under GPLv3 which makes it open source and free.
>
> Contribute by:
> 1. Localization of training data (translation)
> 2. Adding more intents and actions
> 3. Reporting bugs
> 4. Suggesting new features
> NOTICE: I am working on a [RASA NLU](https://rasa.com/docs/rasa/nlu/about/) support
> NOTICE: I am working on a [Rasa NLU](https://rasa.com/docs/rasa/nlu/about/) support
Human Framework is a test automation framework built on top of Natural Language Understanding (NLU) tools.
It currently depend on [Microsoft LUIS (Language Understanding)](https://www.luis.ai/) for Intent Classification.
Human Framework is a test automation framework designed for testers without software programming background by allowing them to write test steps or instructions in their own language like English.

Human Framework tries to introduce a new way of automation testing by making it easier and more natural, by simply writing test steps in English or in any human language the tester is more verse with. For example:
Human Framework uses Natural Language Understanding (NLU) for intent classification and entity extraction to be able to perform specific actions.
It currently depend on [Microsoft LUIS (Language Understanding)](https://www.luis.ai/).

Below is an example of test instructions that Human Framework can understand.
To get an idea of what specific sentences are supported, check the the content of `trials` and `tests` folder.

```
Open chrome browser https://devpost.com
Page title should be "Devpost - The home for hackathons"
Page should contain link "link:About"
Page should contain link "About"
Click link "About"
Page title should be "About us · Devpost"
Close browser
```

LUIS (and other NLU tools) makes it possible to write test cases on any human language.
Current version of Human Framework only supports English.

On a business setup, Human Framework lessens the need for testers who can write programs to perform test automation,
reducing technical requirements. This makes testers think like end-users and not as developers.

Human Framework was inspired by [Robot Framework](https://robotframework.org/) but leans towards
Natural Language Processing (NLP) for writing test cases.

Expand Down Expand Up @@ -124,7 +128,8 @@ Human Framework depends on [Selenium](https://www.seleniumhq.org/) for testing w

### Writing tests

Write a text file (test_*.txt) containing your tests. For example, if we have a file named `test_web.txt`:
Write a text file (test_*.txt) containing your tests and save it to local working directory where you placed the Selenium Drivers.
For example, if we have a file named `test_web.txt`:

```text
open chrome https://python.org
Expand Down
46 changes: 26 additions & 20 deletions hf_actions/web/__init__.py
Expand Up @@ -75,7 +75,7 @@ def assert_title(entities, context):
return False


def _find_element(driver, selector):
def _find_element(driver, selector, element_type=None):
element = None
if selector.startswith('id:'):
id_ = selector.split(':', 1)[1].strip()
Expand All @@ -95,12 +95,18 @@ def _find_element(driver, selector):
elif selector.startswith('css:'):
css = selector.split(':', 1)[1].strip()
element = driver.find_element_by_css_selector(css)
elif selector.startswith('link:'):
link = selector.split(':', 1)[1].strip()
element = driver.find_element_by_link_text(link)
elif selector.startswith('partial link:'):
link = selector.split(':', 1)[1].strip()
elif selector.startswith('partial link:') or element_type == 'partial link':
try:
link = selector.split(':', 1)[1].strip()
except IndexError:
link = selector
element = driver.find_element_by_partial_link_text(link)
elif selector.startswith('link:') or element_type == 'link':
try:
link = selector.split(':', 1)[1].strip()
except IndexError:
link = selector
element = driver.find_element_by_link_text(link)
return element


Expand All @@ -123,57 +129,57 @@ def assert_contain_element(entities, context):
return True
elif element_type == 'button':
def element_found(param):
element = _find_element(driver, selector)
element = _find_element(driver, selector, element_type)
return element and (element.tag_name == element_type or (
element.tag_name == 'input' and element.get_attribute('type') == element_type))

wait.until(element_found)
return True
elif element_type == 'checkbox':
def element_found(param):
element = _find_element(driver, selector)
element = _find_element(driver, selector, element_type)
return element and element.tag_name == 'input' and element.get_attribute('type') == element_type

wait.until(element_found)
return True
elif element_type == 'element':
def element_found(param):
element = _find_element(driver, selector)
element = _find_element(driver, selector, element_type)
return element

wait.until(element_found)
return True
elif element_type == 'image':
def element_found(param):
element = _find_element(driver, selector)
element = _find_element(driver, selector, element_type)
return element and element.tag_name == 'img'

wait.until(element_found)
return True
elif element_type == 'link':
def element_found(param):
element = _find_element(driver, selector)
element = _find_element(driver, selector, element_type)
return element and element.tag_name == 'a'

wait.until(element_found)
return True
elif element_type == 'list':
def element_found(param):
element = _find_element(driver, selector)
element = _find_element(driver, selector, element_type)
return element and element.tag_name in ('ul', 'ol')

wait.until(element_found)
return True
elif element_type == 'radio button':
def element_found(param):
element = _find_element(driver, selector)
element = _find_element(driver, selector, element_type)
return element and element.tag_name == 'input' and element.get_attribute('type') == 'radio'

wait.until(element_found)
return True
elif element_type == 'text field':
def element_found(param):
element = _find_element(driver, selector)
element = _find_element(driver, selector, element_type)
return element and element.tag_name == 'input' and element.get_attribute('type') == 'text'

wait.until(element_found)
Expand All @@ -196,17 +202,17 @@ def click_element(entities, context):
elif entity['type'] == 'string' and not selector:
selector = context['QUERY'][int(entity['startIndex']) + 1:int(entity['endIndex'])]
if element_type == 'button':
element = _find_element(driver, selector)
element = _find_element(driver, selector, element_type)
assert element and (element.tag_name == element_type or (
element.tag_name == 'input' and element.get_attribute('type') == element_type))
elif element_type == 'element':
element = _find_element(driver, selector)
element = _find_element(driver, selector, element_type)
assert element
elif element_type == 'image':
element = _find_element(driver, selector)
element = _find_element(driver, selector, element_type)
assert element and element.tag_name == 'img'
elif element_type == 'link':
element = _find_element(driver, selector)
element = _find_element(driver, selector, element_type)
assert element and element.tag_name == 'a'
if element:
wait = WebDriverWait(driver, 10)
Expand All @@ -232,7 +238,7 @@ def input(entities, context):
elif entity['type'] == 'selector':
selector = context['QUERY'][int(entity['startIndex']) + 1:int(entity['endIndex'])]
if element_type in ('element', 'text field'):
element = _find_element(driver, selector)
element = _find_element(driver, selector, element_type)
assert element
element.send_keys(input_string)
return True
Expand All @@ -253,7 +259,7 @@ def assert_element_status(entities, context):
selector = context['QUERY'][int(entity['startIndex']) + 1:int(entity['endIndex'])]
elif entity['type'] == 'boolean_attribute':
boolean_attribute = entity['entity']
element = _find_element(driver, selector)
element = _find_element(driver, selector, element_type)
if element:
wait = WebDriverWait(driver, 10)
if boolean_attribute in ATTRIBUTE_MAP.keys():
Expand Down
4 changes: 2 additions & 2 deletions setup.cfg
@@ -1,7 +1,7 @@
[metadata]
name=humanframework
version=0.5.2
download_url=https://github.com/roniemartinez/HumanFramework/tarball/0.5.2
version=0.5.3
download_url=https://github.com/roniemartinez/HumanFramework/tarball/0.5.3
description=Human Framework: Test Automation Framework for Humans™
long_description=file:README.md
description-file=README.md
Expand Down
8 changes: 4 additions & 4 deletions tests/action/test_web_action.py
Expand Up @@ -32,7 +32,7 @@ def test_local_file():
assert execute('page should contain element "tag:form"')
assert execute('page should contain element "xpath:/html/body/p"')
assert execute('page should contain image "css:.my-image"')
assert execute('page should contain link "link:Mountain"')
assert execute('page should contain link "Mountain"')
assert execute('page should contain link "partial link:Mount"')
assert execute('page should contain list "id:letters"')
assert execute('page should contain radio button "id:agree"')
Expand All @@ -43,7 +43,7 @@ def test_local_file():
assert execute('click button "id:click-me"')
assert execute('click element "xpath://*[@id="click-me"]"')
assert execute('click image "css:.my-image"')
assert execute('click link "link:Mountain"')
assert execute('click link "Mountain"')
assert execute('close browser')


Expand All @@ -60,7 +60,7 @@ def test_local_file_string():
page should contain element "tag:form"
page should contain element "xpath:/html/body/p"
page should contain image "css:.my-image"
page should contain link "link:Mountain"
page should contain link "Mountain"
page should contain link "partial link:Mount"
page should contain list "id:letters"
page should contain radio button "id:agree"
Expand All @@ -71,7 +71,7 @@ def test_local_file_string():
click button "id:click-me"
click element "xpath://*[@id="click-me"]"
click image "css:.my-image"
click link "link:Mountain"
click link "Mountain"
close browser""")
assert result['STATUS']

Expand Down
6 changes: 6 additions & 0 deletions trials/test_devpost.txt
@@ -0,0 +1,6 @@
Open chrome browser https://devpost.com
Page title should be "Devpost - The home for hackathons"
Page should contain link "About"
Click link "About"
Page title should be "About us · Devpost"
Close browser

0 comments on commit b63b2d7

Please sign in to comment.