Skip to content

Commit

Permalink
Merge branch 'master' into QAWTO-214_update_appium_dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
rgonalo authored Nov 25, 2024
2 parents ac22127 + d9312f2 commit ec6ba97
Show file tree
Hide file tree
Showing 9 changed files with 317 additions and 38 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ target
.vscode

# virtualenv
.venv
venv/
VENV/
ENV/
Expand Down
17 changes: 16 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
Toolium Changelog
=================

v3.1.6
v3.2.1
------

*Release date: In development*

- Allow negative indexes for list elements in context searches. Example: [CONTEXT:element.-1]
- Add support for JSON strings to the `DICT` and `LIST`` replacement. Example: [DICT:{"key": true}], [LIST:[null]]
- Add `REPLACE` replacement, to replace a substring with another. Example: [REPLACE:[CONTEXT:some_url]::https::http]
- Add `TITLE` replacement, to apply Python's title() function. Example: [TITLE:the title]
- Add `ROUND` replacement, float number to a string with the indicated number of decimals. Example: [ROUND:3.3333::2]
- Remove accents from generated file names to avoid errors in some filesystems
- Update Appium-Python-Client requirement to enable 3 and 4 versions
- Deprecate set_text method in InputText class to make it compatible with Appium-Python-Client 3 and 4

v3.2.0
------

*Release date: 2024-09-13*

- Add `run_storage` dictionary to context to store information during the whole test execution
- Update current ChainMap context storages (context.storage, context.feature_storage and context.run_storage)
- Allow to store values from steps into desire storage by using [key], [FEATURE:key] and [RUN:key]

v3.1.5
------

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.1.6.dev0
3.2.0
15 changes: 11 additions & 4 deletions toolium/behave/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import logging
import os
import re
import collections

from toolium.utils import dataset
from toolium.config_files import ConfigFiles
Expand Down Expand Up @@ -50,6 +51,13 @@ def before_all(context):
context.global_status = {'test_passed': True}
create_and_configure_wrapper(context)

# Dictionary to store information during the whole test execution
context.run_storage = dict()
context.storage = context.run_storage

# Method in context to store values in context.storage, context.feature_storage or context.run_storage from steps
context.store_key_in_storage = dataset.store_key_in_storage

# Behave dynamic environment
context.dyn_env = DynamicEnvironment(logger=context.logger)

Expand All @@ -72,10 +80,9 @@ def before_feature(context, feature):
no_driver = 'no_driver' in feature.tags
start_driver(context, no_driver)

# Dictionary to store information between steps
context.storage = dict()
# Dictionary to store information between features
context.feature_storage = dict()
context.storage = collections.ChainMap(context.feature_storage, context.run_storage)

# Behave dynamic environment
context.dyn_env.get_steps_from_feature_description(feature.description)
Expand Down Expand Up @@ -129,8 +136,8 @@ def before_scenario(context, scenario):

context.logger.info("Running new scenario: %s", scenario.name)

# Make sure storage dict are empty in each scenario
context.storage = dict()
# Make sure context storage dict is empty in each scenario and merge with the rest of storages
context.storage = collections.ChainMap(dict(), context.feature_storage, context.run_storage)

# Behave dynamic environment
context.dyn_env.execute_before_scenario_steps(context)
Expand Down
132 changes: 131 additions & 1 deletion toolium/test/utils/test_dataset_map_param_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,79 @@ class Context(object):
assert expected_st == result_st


def test_a_context_param_storage_and_run_storage():
"""
Verification of a mapped parameter as CONTEXT saved in storage and run storage
"""
class Context(object):
pass
context = Context()
context.attribute = "attribute value"
context.storage = {"storage_key": "storage entry value"}
context.run_storage = {"storage_key": "run storage entry value"}
dataset.behave_context = context

result_st = map_param("[CONTEXT:storage_key]")
expected_st = "storage entry value"
assert expected_st == result_st


def test_store_key_in_feature_storage():
"""
Verification of method store_key_in_storage with a mapped parameter as FEATURE saved in feature storage
"""
class Context(object):
pass
context = Context()
context.attribute = "attribute value"
context.storage = {"storage_key": "storage entry value"}
context.feature_storage = {}
dataset.store_key_in_storage(context, "[FEATURE:storage_key]", "feature storage entry value")
dataset.behave_context = context

result_st = map_param("[CONTEXT:storage_key]")
expected_st = "feature storage entry value"
assert expected_st == result_st


def test_store_key_in_run_storage():
"""
Verification of method store_key_in_storage with a mapped parameter as RUN saved in run storage
"""
class Context(object):
pass
context = Context()
context.attribute = "attribute value"
context.storage = {"storage_key": "storage entry value"}
context.run_storage = {}
context.feature_storage = {}
dataset.store_key_in_storage(context, "[RUN:storage_key]", "run storage entry value")
dataset.behave_context = context

result_st = map_param("[CONTEXT:storage_key]")
expected_st = "run storage entry value"
assert expected_st == result_st


def test_a_context_param_using_store_key_in_storage():
"""
Verification of a mapped parameter as CONTEXT saved in storage and run storage
"""
class Context(object):
pass
context = Context()
context.attribute = "attribute value"
context.feature_storage = {}
context.storage = {"storage_key": "previous storage entry value"}
dataset.store_key_in_storage(context, "[FEATURE:storage_key]", "feature storage entry value")
dataset.store_key_in_storage(context, "[storage_key]", "storage entry value")
dataset.behave_context = context

result_st = map_param("[CONTEXT:storage_key]")
expected_st = "storage entry value"
assert expected_st == result_st


def test_a_context_param_without_storage_and_feature_storage():
"""
Verification of a mapped parameter as CONTEXT when before_feature and before_scenario have not been executed, so
Expand Down Expand Up @@ -356,6 +429,64 @@ class Context(object):
assert map_param("[CONTEXT:list.cmsScrollableActions.1.id]") == 'ask-for-qa'


def test_a_context_param_list_correct_negative_index():
"""
Verification of a list with a correct negative index (In bounds) as CONTEXT
"""
class Context(object):
pass
context = Context()

context.list = {
'cmsScrollableActions': [
{
'id': 'ask-for-duplicate',
'text': 'QA duplica'
},
{
'id': 'ask-for-qa',
'text': 'QA no duplica'
},
{
'id': 'ask-for-negative',
'text': 'QA negative index'
}
]
}
dataset.behave_context = context
assert map_param("[CONTEXT:list.cmsScrollableActions.-1.id]") == 'ask-for-negative'
assert map_param("[CONTEXT:list.cmsScrollableActions.-3.id]") == 'ask-for-duplicate'


def test_a_context_param_list_incorrect_negative_index():
"""
Verification of a list with a incorrect negative index (In bounds) as CONTEXT
"""
class Context(object):
pass
context = Context()

context.list = {
'cmsScrollableActions': [
{
'id': 'ask-for-duplicate',
'text': 'QA duplica'
},
{
'id': 'ask-for-qa',
'text': 'QA no duplica'
},
{
'id': 'ask-for-negative',
'text': 'QA negative index'
}
]
}
with pytest.raises(Exception) as excinfo:
map_param("[CONTEXT:list.cmsScrollableActions.-5.id]")
assert "the expression '-5' was not able to select an element in the list" == str(excinfo.value)


def test_a_context_param_list_oob_index():
"""
Verification of a list with an incorrect index (Out of bounds) as CONTEXT
Expand Down Expand Up @@ -438,7 +569,6 @@ def __init__(self):
context.list = ExampleClass()
dataset.behave_context = context

print(context)
with pytest.raises(Exception) as excinfo:
map_param("[CONTEXT:list.cmsScrollableActions.prueba.id]")
assert "the expression 'prueba' was not able to select an element in the list" == str(excinfo.value)
Expand Down
40 changes: 40 additions & 0 deletions toolium/test/utils/test_dataset_replace_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,20 @@ def test_replace_param_now_offsets_with_and_without_format_and_more():
assert param == f'The date {offset_date} was yesterday and I have an appointment at {offset_datetime}'


def test_replace_param_round_with_type_inference():
param = replace_param('[ROUND:7.5::2]')
assert param == 7.5
param = replace_param('[ROUND:3.33333333::3]')
assert param == 3.333


def test_replace_param_round_without_type_inference():
param = replace_param('[ROUND:7.500::2]', infer_param_type=False)
assert param == '7.50'
param = replace_param('[ROUND:3.33333333::3]', infer_param_type=False)
assert param == '3.333'


def test_replace_param_str_int():
param = replace_param('[STR:28]')
assert isinstance(param, str)
Expand Down Expand Up @@ -369,12 +383,22 @@ def test_replace_param_list_strings():
assert param == ['1', '2', '3']


def test_replace_param_list_json_format():
param = replace_param('[LIST:["value", true, null]]')
assert param == ["value", True, None]


def test_replace_param_dict():
param = replace_param("[DICT:{'a':'test1','b':'test2','c':'test3'}]")
assert isinstance(param, dict)
assert param == {'a': 'test1', 'b': 'test2', 'c': 'test3'}


def test_replace_param_dict_json_format():
param = replace_param('[DICT:{"key": "value", "key_2": true, "key_3": null}]')
assert param == {"key": "value", "key_2": True, "key_3": None}


def test_replace_param_upper():
param = replace_param('[UPPER:test]')
assert param == 'TEST'
Expand Down Expand Up @@ -438,3 +462,19 @@ def test_replace_param_partial_string_with_length():
assert param == 'aaaaa is string'
param = replace_param('parameter [STRING_WITH_LENGTH_5] is string')
assert param == 'parameter aaaaa is string'


def test_replace_param_replace():
param = replace_param('[REPLACE:https://url.com::https::http]')
assert param == "http://url.com"
param = replace_param('[REPLACE:https://url.com::https://]')
assert param == "url.com"


def test_replace_param_title():
param = replace_param('[TITLE:hola hola]')
assert param == "Hola Hola"
param = replace_param('[TITLE:holahola]')
assert param == "Holahola"
param = replace_param('[TITLE:hOlA]')
assert param == "HOlA"
1 change: 1 addition & 0 deletions toolium/test/utils/test_path_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
('successful login -- @1.1 john.doe', 'successful_login_1_1_john_doe'),
('successful login -- @1.2 Mark options: {Length=10 Mark=mark File=file_name.jpg}',
'successful_login_1_2_Mark_options___Length_10_Mark_mark_File_file_name_jpg'),
('successful login -- @1.3 acción', 'successful_login_1_3_accion'),
)


Expand Down
Loading

0 comments on commit ec6ba97

Please sign in to comment.