Skip to content

Commit e342f6e

Browse files
committed
Init project
0 parents  commit e342f6e

38 files changed

+2725
-0
lines changed

.github/workflows/pythonpackage.yml

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Python package
2+
3+
on: [push]
4+
5+
jobs:
6+
build:
7+
8+
runs-on: ubuntu-latest
9+
strategy:
10+
max-parallel: 3
11+
matrix:
12+
python-version: [3.5, 3.6, 3.7]
13+
14+
steps:
15+
- uses: actions/checkout@v1
16+
- name: Set up Python ${{ matrix.python-version }}
17+
uses: actions/setup-python@v1
18+
with:
19+
python-version: ${{ matrix.python-version }}
20+
- name: Install dependencies
21+
run: |
22+
python -m pip install --upgrade pip
23+
pip install -r requirements.txt
24+
- name: Lint with flake8
25+
run: |
26+
pip install flake8
27+
# stop the build if there are Python syntax errors or undefined names
28+
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
29+
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
30+
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
31+
- name: Test with nosetests
32+
run: |
33+
pip install nose
34+
pip install nose-html-reporting
35+
nosetests

.github/workflows/pythonpublish.yml

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Upload Python Package
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
jobs:
8+
deploy:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v1
12+
- name: Set up Python
13+
uses: actions/setup-python@v1
14+
with:
15+
python-version: '3.x'
16+
- name: Install dependencies
17+
run: |
18+
python -m pip install --upgrade pip
19+
pip install setuptools wheel twine
20+
- name: Build and publish
21+
env:
22+
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
23+
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
24+
run: |
25+
python setup.py sdist bdist_wheel
26+
twine upload dist/*

.gitignore

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
.idea/
2+
build/
3+
*.pyc
4+
CoreRPAHive.egg-info/
5+
dist/
6+
venv/
7+
Examples/report.html
8+
Examples/log.html
9+
Examples/output.xml
10+
test_save_report_result.xlsx
11+
Examples/test_data/DefaultDemoData-result.xlsx
12+
Examples/geckodriver.log
13+
Examples/RPA_report/
14+
Examples/red.xml
15+
robotframework_corerpahive.egg-info/
16+
Examples/.project
17+
Examples/.pydevproject

Examples/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/libspecs/

Examples/BasicDataDrivenExample.robot

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
*** Setting ***
2+
Library ExcelDataDriver ./test_data/BasicDemoData.xlsx capture_screenshot=Skip
3+
Test Template Validate user data template
4+
5+
*** Test Cases ***
6+
Verify valid user '${username}' ${None} ${None} ${None}
7+
8+
*** Keywords ***
9+
Validate user data template
10+
[Arguments] ${username} ${password} ${email}
11+
Log ${username}
12+
Log ${password}
13+
Log ${email}
14+
Should Be True '${password}' != '${None}'
15+
Should Match Regexp ${email} [A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
from openpyxl.utils import column_index_from_string
2+
from openpyxl.utils.cell import coordinate_from_string
3+
from ExcelDataDriver.ExcelParser.ABCParserStrategy import ABCParserStrategy
4+
from ExcelDataDriver.ExcelTestDataRow import ExcelTestDataRow
5+
6+
7+
class CustomExcelParser(ABCParserStrategy):
8+
9+
def __init__(self):
10+
ABCParserStrategy.__init__(self)
11+
print('Using CustomExcelParser')
12+
self.maximum_column_index_row = 3
13+
self.start_row = 1
14+
15+
def parsing_column_indexs(self, ws):
16+
'''
17+
@param sku: Product SKU
18+
@param normal price: Product normal price
19+
@param normal cost in vat: Product normal cost include vat
20+
@param normal cost ex vat: Product normal cost exclude vat
21+
@param normal cost gp: Product normal GP %
22+
@param promotion price: Product promotion price
23+
@param promotion cost in vat: Product promotion cost include vat
24+
@param promotion cost ex vat: Product promotion cost exclude vat
25+
@param promotion cost gp: Product promotion GP %
26+
'''
27+
ws_column_indexs = {}
28+
29+
##########################
30+
# Parse mandatory property
31+
##########################
32+
for index, row in enumerate(ws.rows):
33+
if index > self.maximum_column_index_row:
34+
break
35+
for cell in row:
36+
if (cell.value is not None) and (cell.value in self.DEFAULT_COLUMN_INDEXS):
37+
ws_column_indexs[cell.value] = column_index_from_string(coordinate_from_string(cell.coordinate)[0])
38+
print('Mandatory : '+str(cell.value) + ' : ' + str(cell.coordinate) + ' : ' + str(column_index_from_string(coordinate_from_string(cell.coordinate)[0])))
39+
if len(ws_column_indexs) > 0:
40+
break
41+
42+
##########################
43+
# Parse optional property
44+
##########################
45+
# Normal Price
46+
# Normal Price
47+
# (In Vat)
48+
# GP (%)
49+
# Promotion Price
50+
# Promotion Price
51+
# (In Vat)
52+
# GP (%)
53+
for index, row in enumerate(ws.rows):
54+
if index > self.maximum_column_index_row:
55+
break
56+
for cell in row:
57+
if (cell.value is not None) and (cell.value not in self.DEFAULT_COLUMN_INDEXS):
58+
column_name = cell.value.lower().strip()
59+
60+
# Normal & Promotion
61+
if column_name == '(in vat)':
62+
if 'normal cost in vat' not in ws_column_indexs:
63+
ws_column_indexs['normal cost in vat'] = column_index_from_string(coordinate_from_string(cell.coordinate)[0])
64+
else:
65+
ws_column_indexs['promotion cost in vat'] = column_index_from_string(coordinate_from_string(cell.coordinate)[0])
66+
67+
elif column_name == '(ex vat)':
68+
if 'normal cost ex vat' not in ws_column_indexs:
69+
ws_column_indexs['normal cost ex vat'] = column_index_from_string(coordinate_from_string(cell.coordinate)[0])
70+
else:
71+
ws_column_indexs['promotion cost ex vat'] = column_index_from_string(coordinate_from_string(cell.coordinate)[0])
72+
73+
elif column_name == 'gp (%)':
74+
if 'normal cost gp' not in ws_column_indexs:
75+
ws_column_indexs['normal cost gp'] = column_index_from_string(coordinate_from_string(cell.coordinate)[0])
76+
else:
77+
ws_column_indexs['promotion cost gp'] = column_index_from_string(coordinate_from_string(cell.coordinate)[0])
78+
79+
ws_column_indexs[column_name] = column_index_from_string(coordinate_from_string(cell.coordinate)[0])
80+
print('Optional : '+str(column_name) + ' : ' + str(cell.coordinate) + ' : ' + str(column_index_from_string(coordinate_from_string(cell.coordinate)[0])))
81+
82+
print('Done parsing column indexes')
83+
return ws_column_indexs
84+
85+
def parse_test_data_properties(self, ws, ws_column_indexs):
86+
test_datas = []
87+
for index, row in enumerate(ws.rows):
88+
if index < self.start_row:
89+
continue
90+
self.is_test_data_valid(ws_column_indexs, ws.title, index, row)
91+
test_data = self.map_data_row_into_test_data_obj(ws_column_indexs, ws.title, index, row)
92+
if test_data is not None:
93+
test_datas.append(test_data)
94+
else:
95+
break
96+
print('Total test datas: ' + str(len(test_datas)))
97+
return test_datas
98+
99+
def is_test_data_valid(self, ws_column_indexes, ws_title, row_index, row):
100+
return True
101+
102+
def map_data_row_into_test_data_obj(self, ws_column_indexes, ws_title, row_index, row):
103+
status = row[ws_column_indexes[self.MANDATORY_TEST_DATA_COLUMN['status']] - 1]
104+
log_message = row[ws_column_indexes[self.MANDATORY_TEST_DATA_COLUMN['log_message']] - 1]
105+
screenshot = row[ws_column_indexes[self.MANDATORY_TEST_DATA_COLUMN['screenshot']] - 1]
106+
tags = row[ws_column_indexes[self.MANDATORY_TEST_DATA_COLUMN['tags']] - 1]
107+
koriico_sku = row[ws_column_indexes['sku'] - 1]
108+
109+
# Excel library send the last row with None data.
110+
if koriico_sku.value is None:
111+
return None
112+
test_data_row = ExcelTestDataRow(ws_title, row_index, row, ws_column_indexes, status, log_message, screenshot, tags)
113+
return test_data_row
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from CustomExcelParser.CustomExcelParser import CustomExcelParser

Examples/CustomParserExample.robot

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
*** Setting ***
2+
Library CustomExcelParser/CustomExcelParser.py
3+
Library ExcelDataDriver ./test_data/Custom_Template.xlsx custom_parser=CustomExcelParser capture_screenshot=OnFailed
4+
Test Template Demo template
5+
6+
7+
*** Test Cases ***
8+
Product promo price update for SKU '${sku}' ${None} ${None} ${None} ${None} ${None} ${None} ${None} ${None} ${None}
9+
10+
*** Keywords ***
11+
Demo template
12+
[Arguments] ${sku} ${normal price} ${normal cost in vat} ${normal cost ex vat} ${normal cost gp} ${promotion price} ${promotion cost in vat} ${promotion cost ex vat} ${promotion cost gp}
13+
Log ${sku}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
*** Setting ***
2+
Library String
3+
Library Collections
4+
Library OperatingSystem
5+
Library SeleniumLibrary
6+
Library ./CustomExcelParser/CustomExcelParser.py
7+
Library ExcelDataDriver manually_test=${True}
8+
9+
10+
*** Tasks ***
11+
Summary_test_result
12+
Merged Excel Report CustomExcelParser
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
*** Setting ***
2+
Library SeleniumLibrary
3+
Library ExcelDataDriver ./test_data/DefaultDemoData.xlsx capture_screenshot_when_fail_only=${True}
4+
Test Template Invalid login
5+
Suite Teardown Close All Browsers
6+
7+
*** Test Cases ***
8+
Login with user '${username}' and password '${password}' ${None} ${None}
9+
10+
*** Keywords ***
11+
Invalid login
12+
[Arguments] ${username} ${password}
13+
Log ${username}
14+
Log ${password}
15+
Close All Browsers
16+
Open Browser https://www.blognone.com/node browser=gc
17+
Should Be Equal As Strings john ${username} msg=Username must be equal to john only not ${username}

Examples/test_data/BasicDemoData.xlsx

13 KB
Binary file not shown.
10.5 KB
Binary file not shown.
12.6 KB
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from enum import Enum
2+
3+
4+
class CaptureScreenShotOption(Enum):
5+
Always = 1
6+
OnFailed = 2
7+
Skip = 3

ExcelDataDriver/Config/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from abc import ABCMeta, abstractmethod
2+
from ExcelDataDriver.ExcelTestDataRow.MandatoryTestDataColumn import MANDATORY_TEST_DATA_COLUMN
3+
from openpyxl.utils import column_index_from_string
4+
from openpyxl.utils.cell import coordinate_from_string
5+
6+
7+
class ABCParserStrategy:
8+
9+
__metaclass__ = ABCMeta
10+
11+
def __init__(self):
12+
self.MANDATORY_TEST_DATA_COLUMN = MANDATORY_TEST_DATA_COLUMN
13+
self.DEFAULT_COLUMN_INDEXS = self.MANDATORY_TEST_DATA_COLUMN.values()
14+
self.start_row = 2
15+
self.max_column = 50
16+
self.maximum_column_index_row = 5
17+
18+
def is_ws_column_valid(self, ws, validate_result):
19+
ws_column_indexes = self.parsing_column_indexs(ws)
20+
diff_column_list = list(set(self.DEFAULT_COLUMN_INDEXS) - set(ws_column_indexes))
21+
if len(diff_column_list) > 0:
22+
validate_result['is_pass'] = False
23+
validate_result['error_message'] += "[" + ws.title + "] Excel column " + ", ".join(
24+
diff_column_list) + " are missing.\r\n"
25+
print("[" + ws.title + "] Excel column " + ", ".join(diff_column_list) + " are missing.")
26+
return validate_result
27+
28+
@abstractmethod
29+
def is_test_data_valid(self, ws_column_indexes, ws_title, row_index, row): pass
30+
31+
@abstractmethod
32+
def map_data_row_into_test_data_obj(self, ws_column_indexes, ws_title, row_index, row): pass
33+
34+
def get_all_worksheet(self, wb):
35+
return list(wb)
36+
37+
def parsing_column_indexs(self, ws):
38+
ws_column_indexs = {}
39+
# Parse mandatory property
40+
for index, row in enumerate(ws.rows):
41+
if index > self.maximum_column_index_row:
42+
break
43+
for cell in row:
44+
if (cell.value is not None) and (cell.value in self.DEFAULT_COLUMN_INDEXS):
45+
ws_column_indexs[cell.value] = column_index_from_string(coordinate_from_string(cell.coordinate)[0])
46+
print('Mandatory : '+str(cell.value) + ' : ' + str(cell.coordinate) + ' : ' + str(column_index_from_string(coordinate_from_string(cell.coordinate)[0])))
47+
self.start_row = index + 1
48+
if len(ws_column_indexs) > 0:
49+
break
50+
51+
# Parse optional property
52+
for index, row in enumerate(ws.rows):
53+
if index > self.maximum_column_index_row:
54+
break
55+
if index != self.start_row - 1:
56+
continue
57+
for cell in row:
58+
if (cell.value is not None) and (cell.value not in self.DEFAULT_COLUMN_INDEXS):
59+
ws_column_indexs[cell.value.lower().strip()] = column_index_from_string(coordinate_from_string(cell.coordinate)[0])
60+
print('Optional : '+str(cell.value.lower().strip()) + ' : ' + str(cell.coordinate) + ' : ' + str(column_index_from_string(coordinate_from_string(cell.coordinate)[0])))
61+
break
62+
print('Done parsing column indexes')
63+
return ws_column_indexs
64+
65+
def parse_test_data_properties(self, ws, ws_column_indexs):
66+
test_datas = []
67+
for index, row in enumerate(ws.rows):
68+
if index < self.start_row:
69+
continue
70+
self.is_test_data_valid(ws_column_indexs, ws.title, index, row)
71+
test_data = self.map_data_row_into_test_data_obj(ws_column_indexs, ws.title, index, row)
72+
if test_data is not None:
73+
test_datas.append(test_data)
74+
else:
75+
break
76+
print('Total test datas: ' + str(len(test_datas)))
77+
return test_datas
78+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from ExcelDataDriver.ExcelParser.ABCParserStrategy import ABCParserStrategy
2+
from ExcelDataDriver.ExcelTestDataRow import ExcelTestDataRow
3+
4+
5+
class DefaultParserStrategy(ABCParserStrategy):
6+
7+
def __init__(self):
8+
ABCParserStrategy.__init__(self)
9+
10+
def is_test_data_valid(self, ws_column_indexes, ws_title, row_index, row):
11+
return True
12+
13+
def map_data_row_into_test_data_obj(self, ws_column_indexes, ws_title, row_index, row):
14+
status = row[ws_column_indexes[self.MANDATORY_TEST_DATA_COLUMN['status']] - 1]
15+
log_message = row[ws_column_indexes[self.MANDATORY_TEST_DATA_COLUMN['log_message']] - 1]
16+
screenshot = row[ws_column_indexes[self.MANDATORY_TEST_DATA_COLUMN['screenshot']] - 1]
17+
tags = row[ws_column_indexes[self.MANDATORY_TEST_DATA_COLUMN['tags']] - 1]
18+
19+
# Excel library send the last row with None data.
20+
if row[-1].value is None:
21+
return None
22+
23+
test_data_row = ExcelTestDataRow(ws_title, row_index, row, ws_column_indexes, status, log_message, screenshot, tags)
24+
return test_data_row

0 commit comments

Comments
 (0)