# -*- coding: utf-8 -*- """ Tests of Internal BoM files - Simple cases for: - CSV - HTML - XML - XLSX - Components units - Sort and groups of RLC_sort - Datasheet as link (HTML and XLSX) - Digi-Key link (HTML and XLSX) - Join columns - ignore_dnf = 0 - html_generate_dnf = 0 - use_alt = 1 (also non contiguous) - COLUMN_RENAME - CSV - HTML - XML - XLSX - group_connectors = 1/0 - Columns are case insensitive - component_aliases - merge_blank_fields - Don't group components - Multipart component (not repeated) - Field collision - test_regex/exclude_any/include_only - No XLSX support Missing: - number_boards - XLSX/HTML colors (for real) For debug information use: pytest-3 --log-cli-level debug """ import os import sys import logging from base64 import b64decode # Look for the 'utils' module from where the script is running prev_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) if prev_dir not in sys.path: sys.path.insert(0, prev_dir) # Utils import from utils import context prev_dir = os.path.dirname(prev_dir) if prev_dir not in sys.path: sys.path.insert(0, prev_dir) from kibot.misc import EXIT_BAD_CONFIG BOM_DIR = 'BoM' REF_COLUMN_NAME = 'References' REF_COLUMN_NAME_R = 'Referencias' QTY_COLUMN_NAME = 'Quantity Per PCB' COMP_COLUMN_NAME = 'Row' COMP_COLUMN_NAME_R = 'Renglón' VALUE_COLUMN_NAME = 'Value' DATASHEET_COLUMN_NAME = 'Datasheet' KIBOM_TEST_HEAD = [COMP_COLUMN_NAME, 'Description', 'Part', REF_COLUMN_NAME, 'Value', 'Footprint', QTY_COLUMN_NAME, DATASHEET_COLUMN_NAME, 'Config'] KIBOM_TEST_HEAD_TOL = [c for c in KIBOM_TEST_HEAD] KIBOM_TEST_HEAD_TOL.insert(-1, 'Tolerance') KIBOM_RENAME_HEAD = [COMP_COLUMN_NAME_R, REF_COLUMN_NAME_R, 'Componente', 'Valor', 'Código Digi-Key', 'Cantidad por PCB'] CONN_HEAD = [COMP_COLUMN_NAME, 'Description', 'Part', REF_COLUMN_NAME, 'Value', 'Footprint', QTY_COLUMN_NAME, DATASHEET_COLUMN_NAME] KIBOM_TEST_COMPONENTS = ['C1', 'C2', 'C3', 'C4', 'R1', 'R2', 'R3', 'R4', 'R5', 'R7', 'R8', 'R9', 'R10'] KIBOM_TEST_COMPONENTS_ALT = ['C1-C4', 'R9-R10', 'R7', 'R8', 'R1-R5'] KIBOM_TEST_COMPONENTS_ALT2 = ['C1-C4', 'R9-R10', 'R7', 'R8', 'R1-R2', 'R4-R5', 'R3'] KIBOM_TEST_EXCLUDE = ['R6'] KIBOM_TEST_GROUPS = 5 KIBOM_PRJ_INFO = ['kibom-test', 'default', 'A', '2020-03-12', None] KIBOM_STATS = [KIBOM_TEST_GROUPS+len(KIBOM_TEST_EXCLUDE), len(KIBOM_TEST_COMPONENTS)+len(KIBOM_TEST_EXCLUDE), len(KIBOM_TEST_COMPONENTS), 1, len(KIBOM_TEST_COMPONENTS)] VARIANTE_PRJ_INFO = ['kibom-variante', 'default', 'A', '2020-03-12', None] LINK_HEAD = ['References', 'Part', 'Value', 'Quantity Per PCB', 'digikey#', 'digikey_alt#', 'manf#'] LINKS_COMPONENTS = ['J1', 'J2', 'R1'] LINKS_EXCLUDE = ['C1'] LINKS_GROUPS = 2 INFO_ROWS = ['Schematic:', 'Variant:', 'Revision:', 'Date:', 'KiCad Version:'] STATS_ROWS = ['Component Groups:', 'Component Count:', 'Fitted Components:', 'Number of PCBs:', 'Total Components:'] DEF_TITLE = 'KiBot Bill of Materials' def check_kibom_test_netlist(rows, ref_column, groups, exclude, comps, ref_sep=' '): """ Checks the kibom-test.sch expected results """ # Groups assert len(rows) == groups logging.debug(str(groups) + " groups OK") # Components if comps: components = [] for r in rows: components.extend(r[ref_column].split(ref_sep)) assert len(components) == len(comps) logging.debug(str(len(comps)) + " components OK") # Excluded if exclude: for ex in exclude: assert ex not in components logging.debug(str(len(exclude)) + " not fitted OK") # All the other components if comps: for c in comps: assert c in components logging.debug("list of components OK") def check_dnc(rows, comp, ref, qty, datasheet=None): for row in rows: if row[ref].find(comp) != -1: assert row[qty] == '1 (DNC)' logging.debug(comp + " is DNC OK") if datasheet is not None: assert row[datasheet].startswith(' t1_v1 logging.debug("* No variant -> t1_v1") rows, header, info = ctx.load_csv(prj+'-bom_(V1).csv') ref_column = header.index(REF_COLUMN_NAME) check_kibom_test_netlist(rows, ref_column, 2, ['R3', 'R4'], ['R1', 'R2']) VARIANTE_PRJ_INFO[1] = 't1_v1' check_csv_info(info, VARIANTE_PRJ_INFO, [4, 20, 2, 1, 2]) # V3 logging.debug("* t1_v3 variant") rows, header, info = ctx.load_csv(prj+'-bom_V3.csv') check_kibom_test_netlist(rows, ref_column, 1, ['R2', 'R3'], ['R1', 'R4']) VARIANTE_PRJ_INFO[1] = 't1_v3' check_csv_info(info, VARIANTE_PRJ_INFO, [3, 20, 2, 1, 2]) ctx.clean_up() def test_int_bom_variant_glb(): """ Assing t1_v1 to default from global. Make sure t1_v3 isn't affected """ prj = 'kibom-variante' ctx = context.TestContextSCH('test_int_bom_variant_glb', prj, 'int_bom_var_t1_glb', BOM_DIR) ctx.run() # No variant -> t1_v1 logging.debug("* No variant -> t1_v1") rows, header, info = ctx.load_csv(prj+'-bom_(V1).csv') ref_column = header.index(REF_COLUMN_NAME) check_kibom_test_netlist(rows, ref_column, 2, ['R3', 'R4'], ['R1', 'R2']) VARIANTE_PRJ_INFO[1] = 't1_v1' check_csv_info(info, VARIANTE_PRJ_INFO, [4, 20, 2, 1, 2]) # V3 logging.debug("* t1_v3 variant") rows, header, info = ctx.load_csv(prj+'-bom_V3.csv') check_kibom_test_netlist(rows, ref_column, 1, ['R2', 'R3'], ['R1', 'R4']) VARIANTE_PRJ_INFO[1] = 't1_v3' check_csv_info(info, VARIANTE_PRJ_INFO, [3, 20, 2, 1, 2]) def test_int_bom_variant_cl_gl(): """ Assing t1_v1 to default from global. Overwrite it from cli to t1_v2. Make sure t1_v3 isn't affected """ prj = 'kibom-variante' ctx = context.TestContextSCH('test_int_bom_variant_cl_gl', prj, 'int_bom_var_t1_glb', BOM_DIR) ctx.run(extra=['--global-redef', 'variant=t1_v2']) ctx.search_err(r'Using command line value .?t1_v2.? for global option .?variant.?') # No variant -> t1_v2 logging.debug("* No variant -> t1_v2") rows, header, info = ctx.load_csv(prj+'-bom_(V2).csv') ref_column = header.index(REF_COLUMN_NAME) check_kibom_test_netlist(rows, ref_column, 1, ['R2', 'R4'], ['R1', 'R3']) VARIANTE_PRJ_INFO[1] = 't1_v2' check_csv_info(info, VARIANTE_PRJ_INFO, [3, 20, 2, 1, 2]) # V3 logging.debug("* t1_v3 variant") rows, header, info = ctx.load_csv(prj+'-bom_V3.csv') check_kibom_test_netlist(rows, ref_column, 1, ['R2', 'R3'], ['R1', 'R4']) VARIANTE_PRJ_INFO[1] = 't1_v3' check_csv_info(info, VARIANTE_PRJ_INFO, [3, 20, 2, 1, 2]) ctx.clean_up() def test_int_bom_ref_separator(): ctx, out = kibom_setup('int_bom_ref_separator') rows, header, info = ctx.load_csv(out) check_csv_info(info, KIBOM_PRJ_INFO, KIBOM_STATS) kibom_verif(rows, header, ref_sep=',') ctx.clean_up() def test_int_bom_variant_5(): prj = 'kibom-variant_5' ctx = context.TestContextSCH('test_int_bom_variant_5', prj, 'int_bom_var_5_csv', BOM_DIR) ctx.run() rows, header, info = ctx.load_csv(prj+'-bom.csv') ref_column = header.index(REF_COLUMN_NAME) check_kibom_test_netlist(rows, ref_column, 1, ['C1', 'C2', 'R1'], ['R2']) ctx.clean_up()