Skip to content
This repository was archived by the owner on May 13, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed docs/source/_static/img/data-infile.png
Binary file not shown.
8 changes: 0 additions & 8 deletions docs/source/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,6 @@ Take a screenshot after 'test' function ends. Default is False.

Highlight elements on the screen when found. Default is False

### test_data

The location to store test data. Options are: 'infile' and 'csv'. Default is 'csv.'.

With 'test_data' = 'infile' data is stored inside the test file as a list of dictionaries.

With 'test_data' = 'csv' data is stored in a csv file in the same folder of the test and with the same name, e.g.: /tests/test1.py -> /tests/test1.csv

### wait_hook

Custom wait method to use for every action, that can be specific to each application. It must be defined inside extend.py
Expand Down
97 changes: 60 additions & 37 deletions docs/source/test-data.md
Original file line number Diff line number Diff line change
@@ -1,64 +1,87 @@
Test data
==================================================

The data for each test can be stored inside the test or in a separate CSV file.
To select which location Golem should use, set the *test_data* setting to 'csv' or 'infile'.
A test file can have one of three different types of data sources: CSV, JSON and internal.


## CSV Data

When *"test_data"* setting is set to "csv" the data will be saved in a separate csv file in the same folder as the test.

**Note**: All csv values are considered strings. If you need different value types use the 'infile' setting.
The CSV data file must have the same filename as the test file and be located in the same folder.
Note that: All CSV values are considered strings.
If you need different value types use JSON or internal data.

**test_01.csv**
```
name,age
John,23
Marie,32
```

## Infile Data
**test_01.py**
```python
def test(data):
print(data.name, data.age)
```

When using *"test_data": "infile"* in settings different Python variable types can be used. **Strings must be defined in quotes in the Web Module data table**.
## JSON Data

![data table infile](_static/img/data-infile.png "Test With Data Table")
The JSON data file must have the same filename as the test file and be located in the same folder.
Valid JSON data must be an object (dictionary), or an array of objects (list of dictionaries).
Invalid data is ignored.

The test code looks like this:
**test_02.json**
```json
[
{
"item_id": 5143,
"price": 2134.55,
},
{
"item_id": 8429,
"price": 462.21,
}
]
```

**test_with_infile_data.py**
**test_01.py**
```python
def test(data):
print(data.item_id, data.price)
```
description = 'Hey! this test has infile data!'

## Internal Data

Internal data must be a variable with name "data" defined inside the test file and of type either dictionary or list of dictionaries.

**test_03.py**
```python

data = [
{
'numbers': 12,
'boolean': False,
'none': None,
'list': [1,2,3],
'dict': {'key': 'string'},
'tuple': (1, '2', 3.0),
'str_single': 'test',
'str_double': "test",
'name': 'Chicken S Rice',
'price': 100,
'discount': True
},
{
'numbers': 12,
'boolean': True,
'none': None,
'list': ['a', 'b', 'c'],
'dict': {"key": 12},
'tuple': ('a', 'a"b"c', "a'b'c"),
'str_single': 'a "b" c',
'str_double': "a 'b' c",
'customer': 'Paneer Schezwan Rice',
'price': 110
'discount': False,
},
]

def test(data):
navigate('some_url')
send_keys(('id', 'searchInput'), data.str_single)
print(data.name, data.price, data.discount)

```

Infile data is stored as a list of dictionaries. Each dictionary is a different test set.
## Repeating the test based on data

When the data is a list (or array) with more than one item, or a CSV table with more than one row,
the test will repeat once per each test data set.

## Adding Values to Data at Runtime

Values can be added to the data object using the *store* action
Values can be added to the data object using the *store* action.

```python
def test(data):
Expand All @@ -68,15 +91,15 @@ def test(data):

## Accesing data during the test

Data object is present in the execution module during the test.
The data object is present in the execution module during the test.

```python
from golem import execution

print(execution.data.my_value)
```

Data object is shared among all the functions of a test file::
The data object is shared among all the test functions of a test file:

```python
def setup(data):
Expand All @@ -94,7 +117,7 @@ def test_two(data):

The *get_data* action can be used to retrieve the data object:

page1.py
**page1.py**
```python
from golem import actions

Expand All @@ -109,7 +132,7 @@ This file can be used to store environment specific data, such as the URL and th

For example:

environments.json
**environments.json**
```json
{
"testing": {
Expand Down Expand Up @@ -139,7 +162,7 @@ environments.json

During the execution of the test, the environment data is stored in data.env:

test1.py
**test1.py**
```python
def test(data):
navigate(data.env.url)
Expand All @@ -158,7 +181,7 @@ There are two ways to define the environment (or environments) for a test or sui

2. from the definition of a suite:

suite1.py
**suite1.py**
```python
environments = ['testing']
```
Expand Down
65 changes: 7 additions & 58 deletions docs/source/tutorial-part-2.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,27 +56,22 @@ golem run <project_name> validate_article_title

## Managing Test Data

The data for each test can be stored inside the test or in a separate csv file.
The data for each test can be stored inside the test file, in CSV or JSON files.

To select which location Golem should use, set the *test_data* setting to 'csv' or 'infile'.
### Using the CSV Data Table

**Note**: All csv values are considered as strings. If you need different value types use the 'infile' setting.
Let's rewrite the previous test but extracting all the data outside the code:


### Using the Data Table

Let's rewrite the previous test but extracting all the data outside of the code:

The values of a test can be defined using the data table in the Web Module at the bottom of the test builder.
This will generate a csv file in the same folder as the test with the following data:
In the Test Builder select *Add Data Source* -> *CSV*.
Then we fill the table with the following values:

**validate_article_title.csv**
```
URL,search_value,article_title
http://en.wikipedia.org/,automation,Automation
```

Then we refactor the test to use the data object instead of hardcoded values:
And we refactor the test to use the data object instead of hardcoded values:

**validate_article_title.py**
```python
Expand Down Expand Up @@ -111,53 +106,7 @@ http://fr.wikipedia.org/,soupe à l'oignon,Soupe à l'oignon

Using this data file, Golem will run the same test 4 times, using each time a different data set.

<div class="admonition note">
<p class="first admonition-title">Check this out</p>
<p>In the third and fourth rows we used a different URL, so we can even point the same test to different environments by just changing the data sets.</p>
</div>

### Infile data

When using *"test_data": "infile"* in settings.json different Python variable types can be used. **Strings must be defined in quotes in the Web Module data table**.

![data table infile](_static/img/data-infile.png "Test With Data Table")

The test code looks like this:

**test_with_infile_data.py**
```
description = 'Hey! this test has infile data!'

data = [
{
'numbers': 12,
'boolean': False,
'none': None,
'list': [1,2,3],
'dict': {'key': 'string'},
'tuple': (1, '2', 3.0),
'str_single': 'test',
'str_double': "test",
},
{
'numbers': 12,
'boolean': True,
'none': None,
'list': ['a', 'b', 'c'],
'dict': {"key": 12},
'tuple': ('a', 'a"b"c', "a'b'c"),
'str_single': 'a "b" c',
'str_double': "a 'b' c",
},
]

def test(data):
navigate('some_url')
send_keys(('id', 'searchInput'), data.str_single)

```

Infile data is stored as a list of dictionaries. Each dictionary is a different test set.
Test data can also be [JSON](test-data.html#json-data) and [internal](test-data.html#internal-data).


## Using Page Objects
Expand Down
4 changes: 2 additions & 2 deletions golem/core/file_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ def generate_file_structure_dict(full_path, original_path=None):
if elem not in ['__pycache__']:
directories.append(elem)
else:
cond1 = elem not in ['__init__.py', '.DS_Store']
cond2 = not elem.endswith('.csv')
cond1 = elem.endswith('.py')
cond2 = elem not in ['__init__.py', '.DS_Store']
if cond1 and cond2:
files.append(os.path.splitext(elem)[0])
for directory in directories:
Expand Down
4 changes: 0 additions & 4 deletions golem/core/settings_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@
// Highlight elements on the screen when found
"highlight_elements": false,

// Where to store test data. Options are: 'infile', 'csv'. Default is 'csv'
"test_data": "csv",

// Custom wait method to use before each step, must be defined inside extend.py
"wait_hook": null,

Expand Down Expand Up @@ -83,7 +80,6 @@
('screenshot_on_step', False),
('screenshot_on_end', False),
('highlight_elements', False),
('test_data', 'csv'),
('wait_hook', None),
('default_browser', 'chrome'),
('chromedriver_path', None),
Expand Down
42 changes: 26 additions & 16 deletions golem/core/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,20 @@ def _print_extra_blank_line():
test_.append('')
test_.append('pages = {}'.format(_format_page_string(pages)))

if test_data:
if settings['test_data'] == 'infile':
_print_extra_blank_line()
test_.append('')
test_.append('data = {}'.format(_format_data(test_data)))
test_data_module.remove_csv_if_exists(project, test_name)
else:
test_data_module.save_external_test_data_file(project, test_name, test_data)
if test_data['csv'] is not None:
test_data_module.save_csv_test_data(project, test_name, test_data['csv'])
else:
test_data_module.remove_csv_if_present(project, test_name)

if test_data['json'] is not None and test_data['json'].strip():
test_data_module.save_json_test_data(project, test_name, test_data['json'])
else:
test_data_module.remove_json_data_if_present(project, test_name)

if test_data['internal'] is not None and test_data['internal'].strip():
_print_extra_blank_line()
test_.append('')
test_.append(test_data['internal'])

if skip:
_print_extra_blank_line()
Expand Down Expand Up @@ -217,18 +223,22 @@ def _print_extra_blank_line():
f.write('\n'.join(test_))


def edit_test_code(project, test_name, content, table_test_data):
def edit_test_code(project, test_name, content, test_data=None):
path = Test(project, test_name).path
with open(path, 'w', encoding='utf-8') as f:
f.write(content)
# save test data
settings = settings_manager.get_project_settings(project)
if settings['test_data'] == 'csv':
# save csv data
test_data_module.save_external_test_data_file(project, test_name, table_test_data)
elif settings['test_data'] == 'infile':
# remove csv files
test_data_module.remove_csv_if_exists(project, test_name)
if test_data is not None:
if test_data['csv'] is not None:
test_data_module.save_csv_test_data(project, test_name, test_data['csv'])
test_data_module.remove_json_data_if_present(project, test_name)
else:
test_data_module.remove_csv_if_present(project, test_name)

if test_data['json'] is not None and test_data['json'].strip():
test_data_module.save_json_test_data(project, test_name, test_data['json'])
else:
test_data_module.remove_json_data_if_present(project, test_name)


def delete_test(project, test_name):
Expand Down
Loading