def __init__(self): self.util = Utilities() self.auth = Authenticator() self.token = self.auth.get_token() self.headers = { "Authorization": "Bearer " + str(self.token), 'Content-Type': 'application/json' }
def __init__(self, data_source, dashboard, test_data): self.data_source = data_source self.dashboard = dashboard self.test_data = test_data self.big_query = BigQueryHandler() self.util = Utilities() self.sisense = SisenseApiHandler() self.widgets_id = self.util.get_widgets_id_mapping(dashboard) self.applicable_filters = self.util.get_applicable_filters_mapping( dashboard) self.query_name = None
def format_value(value): value = Utilities.change_none_to_zero(str(value)) value = Utilities.round_off(value) return value
def __init__(self, dashboard): self.util = Utilities() self.widget_jaql = {} self.dim = self.util.get_dim_mapping(dashboard)
class JaqlConstructor: def __init__(self, dashboard): self.util = Utilities() self.widget_jaql = {} self.dim = self.util.get_dim_mapping(dashboard) @staticmethod def construct_test_data(test_data): test_data_dict = {} for k, v in test_data.items(): test_data_dict[k] = { 'Values': v['Values'], 'FilterCond': v['FilterCond'] } return test_data_dict @staticmethod def construct_test_data_with_applicable_filters(test_data, query_name, applicable_filters): test_data_dict = {} for k, v in test_data.items(): if k in applicable_filters[query_name]: test_data_dict[k] = { 'Values': v['Values'], 'FilterCond': v['FilterCond'] } return test_data_dict def add_filter(self, filter_name, values): filter_json = json.load(open("resources/filter_template.json", 'r')) if 'date' in filter_name.lower(): filter_json['jaql']['level'] = 'days' filter_json['jaql']['firstday'] = 'mon' (table, column) = self.dim[filter_name].split('.') filter_json['jaql']['table'] = table filter_json['jaql']['column'] = column filter_json['jaql']['dim'] = "[{0}]".format(self.dim[filter_name]) test_data = values['Values'] filter_cond = values['FilterCond'] if len(filter_cond) > 1: if 'all' not in test_data and '' != test_data[0].strip(): for i in range(len(filter_cond)): filter_json['jaql']['filter'][ filter_cond[i]] = test_data[i] else: filter_json['jaql']['filter']['all'] = 'true' else: if 'all' not in test_data and '' != test_data[0].strip(): if len(test_data) > 1: filter_json['jaql']['filter'][filter_cond[0]] = test_data else: filter_json['jaql']['filter'][ filter_cond[0]] = test_data[0] else: filter_json['jaql']['filter']['all'] = 'true' self.widget_jaql['metadata'].append(filter_json) def construct_jaql(self, widgets_id, widget, test_data, query_name, applicable_filters): self.get_widget_jaql(widgets_id, widget) if query_name is not None: constructed_test_data = self.construct_test_data_with_applicable_filters( test_data, query_name, applicable_filters) else: constructed_test_data = self.construct_test_data(test_data) for k, v in constructed_test_data.items(): self.add_filter(k, v) return self.widget_jaql def get_widget_jaql(self, widgets_id, widget): self.widget_jaql = SisenseApiHandler().get(widgets_id['dashboard_id'], widgets_id[widget])
class Comparator: def __init__(self, data_source, dashboard, test_data): self.data_source = data_source self.dashboard = dashboard self.test_data = test_data self.big_query = BigQueryHandler() self.util = Utilities() self.sisense = SisenseApiHandler() self.widgets_id = self.util.get_widgets_id_mapping(dashboard) self.applicable_filters = self.util.get_applicable_filters_mapping( dashboard) self.query_name = None def assert_equals(self, expected, actual_row, categories, header): actual = actual_row[header] category_val = [actual_row[f] for f in categories ] if categories is not None else None assert actual == expected, \ 'Failed at Row ' + str(category_val) + ' Column [' + header + '] ' \ '\n Expected [' + expected + '] & Actual [' + actual + ']' def get_sisense_data(self, widget): json_obj = JaqlConstructor(self.dashboard) \ .construct_jaql(self.widgets_id, widget, self.test_data, self.query_name, self.applicable_filters) return self.sisense.post(self.data_source, json_obj) def get_big_query_data(self, widget): query = self.big_query.formatted_query('resources/' + self.dashboard + '/queries/' + widget + '.sql') if '->' in query: key_val = query.split('->', 1) self.query_name = key_val[0] query = key_val[1] if self.query_name is None: self.big_query.construct_test_data(self.test_data) else: self.big_query.construct_test_data_with_applicable_filters( self.test_data, self.query_name, self.applicable_filters) return self.big_query.execute(query) def compare(self, widget, categories=None): expected = self.get_big_query_data(widget) actual = self.get_sisense_data(widget) for exp_row in expected: act_row = self.get_matched_record(exp_row, actual, categories) for header in exp_row.keys(): self.assert_equals(exp_row[header], act_row, categories, header) @staticmethod def get_matched_record(exp_row, actual, categories): if categories is not None and len(actual) > 1: flag = False for act_row in actual: for col in categories: if act_row[col] == exp_row[col]: flag = True else: flag = False break if flag: return act_row if not flag: assert False, 'Record [' + str( exp_row) + '] is not there in Sisense' else: return actual[0]
class SisenseApiHandler: def __init__(self): self.util = Utilities() self.auth = Authenticator() self.token = self.auth.get_token() self.headers = { "Authorization": "Bearer " + str(self.token), 'Content-Type': 'application/json' } def get(self, dashboard_id, widget_id): widget_jaql = {} try: url = SisenseApiHandler.get_widget_jaql_endpoint( self, dashboard_id, widget_id) response = requests.get(url, headers=self.headers) assert response.status_code == 200 parsed_response = response.json() panels = parsed_response['metadata']['panels'] widget_jaql['metadata'] = self.frame_jaql(panels) except requests.exceptions.RequestException as err: print('Error Occurred while GET request!' + str(err)) return widget_jaql def post(self, data_source, payload): act_dict = {} try: url = SisenseApiHandler.get_endpoint(self, data_source) response = requests.post(url, data=json.dumps(payload), headers=self.headers) assert response.status_code == 200 act_dict = self.response_parser(response) except requests.exceptions.RequestException as err: print('Error Occurred while POST request!' + str(err)) return act_dict def build_cube(self, dashboard): try: print('Building ElastiCube...') data_model_id = self.util.get_widgets_id_mapping( dashboard)['data_model_id'] url = self.auth.get_base_url() + 'v2/builds' body = { "datamodelId": data_model_id, "buildType": "full", "rowLimit": 0, "schemaOrigin": "latest" } response = requests.post(url, data=json.dumps(body), headers=self.headers) assert response.status_code == 201 build_id = response.json()['oid'] self.wait_till_build_completed(build_id) except requests.exceptions.RequestException as err: print('Error Occurred while building cube!' + str(err)) def wait_till_build_completed(self, build_id): build_status = 'building' while build_status == 'building': time.sleep(30) build_status = self.get_build_status(build_id) if build_status == 'failed': assert False, 'ElastiCube build FAILED!' else: print('ElastiCube build successful!') def get_build_status(self, build_id): url = self.auth.get_base_url() + 'v2/builds/' + build_id response = requests.get(url, headers=self.headers) assert response.status_code == 200 return response.json()['status'] def response_parser(self, response): response = response.json() headers = response['headers'] values = response['values'] list_output = [] resp = {} for idx, value in enumerate(values): if type(values[idx]) is list: resp = {} for i, item in enumerate(value): header = self.format_header(headers[i]) resp[header.lower()] = self.format_value( header, str(item['data'])) list_output.append(resp) else: header = self.format_header(headers[idx]) resp[header.lower()] = self.format_value( header, str(values[idx]['data'])) if not list_output: list_output.append(resp) return list_output def format_header(self, header): header = re.sub(r'[^a-zA-Z0-9\s-]', '', header).strip() while header[0].isdigit(): header = re.sub('^[0-9]', '', header).strip() header = re.sub(r'[\s-]+', '_', header) header = header.rstrip('_') return header def format_value(self, header, value): value = self.util.extract_month_year( value) if 'months_in_date' == header.lower( ) else self.util.extract_date(value) value = '0' if value == 'N\\A' else value value = self.util.round_off(value) return value def assert_response_status_code(self, status_code): assert status_code == 200 def get_widget_jaql_endpoint(self, dashboard_id, widget_id): return self.auth.get_base_url() + "dashboards/{0}/widgets/{1}".format( dashboard_id, widget_id) def get_endpoint(self, data_source): return self.auth.get_base_url() + "datasources/{0}/jaql".format( data_source) def frame_jaql(self, panels): jaql_list = [] for panel in panels: for item in panel['items']: if ("disabled" in item and not item['disabled']) or ("disabled" not in item): jaql_list.append({"jaql": item["jaql"]}) return jaql_list
from src.utils.utilities import Utilities comparator_obj = Utilities().init_test_data('dashboard_name') class TestDashboard: testdata = comparator_obj def test_widget(self, attribute): attribute.compare('widget_name')