Added simple CSV and HTML test for the internal BoM.
This commit is contained in:
parent
d55846fe85
commit
7d56b59ba4
4
Makefile
4
Makefile
|
|
@ -11,6 +11,10 @@ ifneq ("$(wildcard *.yaml)","")
|
|||
$(error Move away any config file)
|
||||
endif
|
||||
|
||||
ifneq ("$(wildcard *.sch)","")
|
||||
$(error Move away any schematic file)
|
||||
endif
|
||||
|
||||
deb:
|
||||
perl debian/make_postinst.pl > debian/postinst
|
||||
chmod +x debian/postinst
|
||||
|
|
|
|||
|
|
@ -0,0 +1,180 @@
|
|||
EESchema Schematic File Version 4
|
||||
EELAYER 30 0
|
||||
EELAYER END
|
||||
$Descr A4 11693 8268
|
||||
encoding utf-8
|
||||
Sheet 1 1
|
||||
Title "KiBom Test Schematic"
|
||||
Date "2020-03-12"
|
||||
Rev "A"
|
||||
Comp "https://github.com/SchrodingersGat/KiBom"
|
||||
Comment1 ""
|
||||
Comment2 ""
|
||||
Comment3 ""
|
||||
Comment4 ""
|
||||
$EndDescr
|
||||
$Comp
|
||||
L Device:R R1
|
||||
U 1 1 5E6A2873
|
||||
P 2200 2550
|
||||
F 0 "R1" V 2280 2550 50 0000 C CNN
|
||||
F 1 "10K" V 2200 2550 50 0000 C CNN
|
||||
F 2 "Resistor_SMD:R_0805_2012Metric" V 2130 2550 50 0001 C CNN
|
||||
F 3 "~" H 2200 2550 50 0001 C CNN
|
||||
1 2200 2550
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L Device:R R2
|
||||
U 1 1 5E6A330D
|
||||
P 2500 2550
|
||||
F 0 "R2" V 2580 2550 50 0000 C CNN
|
||||
F 1 "10K" V 2500 2550 50 0000 C CNN
|
||||
F 2 "Resistor_SMD:R_0805_2012Metric" V 2430 2550 50 0001 C CNN
|
||||
F 3 "~" H 2500 2550 50 0001 C CNN
|
||||
1 2500 2550
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L Device:R R3
|
||||
U 1 1 5E6A35E1
|
||||
P 2750 2550
|
||||
F 0 "R3" V 2830 2550 50 0000 C CNN
|
||||
F 1 "10K" V 2750 2550 50 0000 C CNN
|
||||
F 2 "Resistor_SMD:R_0805_2012Metric" V 2680 2550 50 0001 C CNN
|
||||
F 3 "~" H 2750 2550 50 0001 C CNN
|
||||
1 2750 2550
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L Device:R R4
|
||||
U 1 1 5E6A37B2
|
||||
P 3000 2550
|
||||
F 0 "R4" V 3080 2550 50 0000 C CNN
|
||||
F 1 "10K" V 3000 2550 50 0000 C CNN
|
||||
F 2 "Resistor_SMD:R_0805_2012Metric" V 2930 2550 50 0001 C CNN
|
||||
F 3 "~" H 3000 2550 50 0001 C CNN
|
||||
1 3000 2550
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L Device:R R5
|
||||
U 1 1 5E6A39EB
|
||||
P 3250 2550
|
||||
F 0 "R5" V 3330 2550 50 0000 C CNN
|
||||
F 1 "10K" V 3250 2550 50 0000 C CNN
|
||||
F 2 "Resistor_SMD:R_0805_2012Metric" V 3180 2550 50 0001 C CNN
|
||||
F 3 "~" H 3250 2550 50 0001 C CNN
|
||||
1 3250 2550
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
Text Notes 3500 2550 0 50 ~ 0
|
||||
5 x 10K resistors in 0805 package
|
||||
$Comp
|
||||
L Device:R R6
|
||||
U 1 1 5E6A3CA0
|
||||
P 2200 3100
|
||||
F 0 "R6" V 2280 3100 50 0000 C CNN
|
||||
F 1 "4K7" V 2200 3100 50 0000 C CNN
|
||||
F 2 "Resistor_SMD:R_0805_2012Metric" V 2130 3100 50 0001 C CNN
|
||||
F 3 "~" H 2200 3100 50 0001 C CNN
|
||||
F 4 "DNF" V 2200 3100 50 0001 C CNN "Config"
|
||||
1 2200 3100
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L Device:R R7
|
||||
U 1 1 5E6A3F38
|
||||
P 2500 3100
|
||||
F 0 "R7" V 2580 3100 50 0000 C CNN
|
||||
F 1 "4700" V 2500 3100 50 0000 C CNN
|
||||
F 2 "Resistor_SMD:R_0805_2012Metric" V 2430 3100 50 0001 C CNN
|
||||
F 3 "~" H 2500 3100 50 0001 C CNN
|
||||
F 4 "DNC" V 2500 3100 50 0001 C CNN "Config"
|
||||
1 2500 3100
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L Device:R R8
|
||||
U 1 1 5E6A4181
|
||||
P 2750 3100
|
||||
F 0 "R8" V 2830 3100 50 0000 C CNN
|
||||
F 1 "4.7K" V 2750 3100 50 0000 C CNN
|
||||
F 2 "Resistor_SMD:R_0805_2012Metric" V 2680 3100 50 0001 C CNN
|
||||
F 3 "~" H 2750 3100 50 0001 C CNN
|
||||
1 2750 3100
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
Text Notes 3500 3150 0 50 ~ 0
|
||||
3 x 4K7 resistors in 0805 package\nNote: Values are identical even if specified differently
|
||||
$Comp
|
||||
L Device:R R9
|
||||
U 1 1 5E6A448B
|
||||
P 2200 3650
|
||||
F 0 "R9" V 2280 3650 50 0000 C CNN
|
||||
F 1 "4K7" V 2200 3650 50 0000 C CNN
|
||||
F 2 "Resistor_SMD:R_0603_1608Metric" V 2130 3650 50 0001 C CNN
|
||||
F 3 "~" H 2200 3650 50 0001 C CNN
|
||||
1 2200 3650
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L Device:R R10
|
||||
U 1 1 5E6A491A
|
||||
P 2500 3650
|
||||
F 0 "R10" V 2580 3650 50 0000 C CNN
|
||||
F 1 "4K7" V 2500 3650 50 0000 C CNN
|
||||
F 2 "Resistor_SMD:R_0603_1608Metric" V 2430 3650 50 0001 C CNN
|
||||
F 3 "~" H 2500 3650 50 0001 C CNN
|
||||
1 2500 3650
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
Text Notes 3500 3650 0 50 ~ 0
|
||||
3 x 4K7 resistors in 0603 package
|
||||
Text Notes 550 950 0 50 ~ 0
|
||||
This schematic serves as a test-file for the KiBom export script.\n\nAfter making a change to the schematic, remember to re-export the BOM to generate the intermediate .xml file\n\n(The testing framework cannot perform the netlist-export step!)
|
||||
$Comp
|
||||
L Device:C C1
|
||||
U 1 1 5E6A62CC
|
||||
P 6650 2550
|
||||
F 0 "C1" H 6675 2650 50 0000 L CNN
|
||||
F 1 "10nF" H 6675 2450 50 0000 L CNN
|
||||
F 2 "Capacitor_SMD:C_0603_1608Metric" H 6688 2400 50 0001 C CNN
|
||||
F 3 "~" H 6650 2550 50 0001 C CNN
|
||||
1 6650 2550
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L Device:C C2
|
||||
U 1 1 5E6A6854
|
||||
P 7050 2550
|
||||
F 0 "C2" H 7075 2650 50 0000 L CNN
|
||||
F 1 "10n" H 7075 2450 50 0000 L CNN
|
||||
F 2 "Capacitor_SMD:C_0603_1608Metric" H 7088 2400 50 0001 C CNN
|
||||
F 3 "~" H 7050 2550 50 0001 C CNN
|
||||
1 7050 2550
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L Device:C C3
|
||||
U 1 1 5E6A6A34
|
||||
P 7450 2550
|
||||
F 0 "C3" H 7475 2650 50 0000 L CNN
|
||||
F 1 "0.01uF" H 7475 2450 50 0000 L CNN
|
||||
F 2 "Capacitor_SMD:C_0603_1608Metric" H 7488 2400 50 0001 C CNN
|
||||
F 3 "~" H 7450 2550 50 0001 C CNN
|
||||
1 7450 2550
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$Comp
|
||||
L Device:C C4
|
||||
U 1 1 5E6A6CB6
|
||||
P 7900 2550
|
||||
F 0 "C4" H 7925 2650 50 0000 L CNN
|
||||
F 1 "0.01uf" H 7925 2450 50 0000 L CNN
|
||||
F 2 "Capacitor_SMD:C_0603_1608Metric" H 7938 2400 50 0001 C CNN
|
||||
F 3 "~" H 7900 2550 50 0001 C CNN
|
||||
1 7900 2550
|
||||
1 0 0 -1
|
||||
$EndComp
|
||||
$EndSCHEMATC
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
"""
|
||||
Tests of Internal BoM files
|
||||
|
||||
For debug information use:
|
||||
pytest-3 --log-cli-level debug
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
from copy import deepcopy
|
||||
# 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 kiplot.misc import (BOM_ERROR)
|
||||
|
||||
BOM_DIR = 'BoM'
|
||||
REF_COLUMN_NAME = 'Reference'
|
||||
QTY_COLUMN_NAME = 'Quantity Per PCB'
|
||||
KIBOM_TEST_HEAD = ['Component', 'Description', 'Part', REF_COLUMN_NAME, 'Value', 'Footprint', QTY_COLUMN_NAME, 'Datasheet',
|
||||
'config']
|
||||
KIBOM_TEST_COMPONENTS = ['C1', 'C2', 'C3', 'C4', 'R1', 'R2', 'R3', 'R4', 'R5', 'R7', 'R8', 'R9', 'R10']
|
||||
KIBOM_TEST_EXCLUDE = ['R6']
|
||||
KIBOM_TEST_GROUPS = 5
|
||||
|
||||
|
||||
def check_kibom_test_netlist(rows, ref_column, groups, exclude, comps):
|
||||
""" Checks the kibom-test.xml 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(' '))
|
||||
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):
|
||||
for row in rows:
|
||||
if row[ref].find(comp) != -1:
|
||||
assert row[qty] == '1 (DNC)'
|
||||
logging.debug(comp + " is DNC OK")
|
||||
return
|
||||
|
||||
|
||||
def test_int_bom_simple_csv():
|
||||
prj = 'kibom-test'
|
||||
ext = 'csv'
|
||||
ctx = context.TestContext('test_int_bom_simple_csv', prj, 'int_bom_simple_csv', BOM_DIR)
|
||||
ctx.run(no_board_file=True, extra=['-e', os.path.join(ctx.get_board_dir(), prj+'.sch')])
|
||||
out = prj + '-bom.' + ext
|
||||
rows, header = ctx.load_csv(out)
|
||||
assert header == KIBOM_TEST_HEAD
|
||||
ref_column = header.index(REF_COLUMN_NAME)
|
||||
qty_column = header.index(QTY_COLUMN_NAME)
|
||||
check_kibom_test_netlist(rows, ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
|
||||
check_dnc(rows, 'R7', ref_column, qty_column)
|
||||
ctx.clean_up()
|
||||
|
||||
|
||||
def test_int_bom_simple_html():
|
||||
prj = 'kibom-test'
|
||||
ext = 'html'
|
||||
ctx = context.TestContext('test_int_bom_simple_html', prj, 'int_bom_simple_html', BOM_DIR)
|
||||
ctx.run(no_board_file=True, extra=['-e', os.path.join(ctx.get_board_dir(), prj+'.sch')])
|
||||
out = prj + '-bom.' + ext
|
||||
rows, headers = ctx.load_html(out)
|
||||
# Test we got the normal and DNF tables
|
||||
assert len(rows) == 2
|
||||
assert len(headers) == 2
|
||||
# Test both tables has the same headings and they are the expected
|
||||
assert headers[0] == headers[1]
|
||||
head_no_comp = deepcopy(KIBOM_TEST_HEAD)
|
||||
head_no_comp[0] = '' # HTML numbered column doesn't have a name
|
||||
assert headers[0] == head_no_comp
|
||||
# Look for reference and quantity columns
|
||||
ref_column = headers[0].index(REF_COLUMN_NAME)
|
||||
qty_column = headers[0].index(QTY_COLUMN_NAME)
|
||||
# Check the normal table
|
||||
check_kibom_test_netlist(rows[0], ref_column, KIBOM_TEST_GROUPS, KIBOM_TEST_EXCLUDE, KIBOM_TEST_COMPONENTS)
|
||||
check_dnc(rows[0], 'R7', ref_column, qty_column)
|
||||
# Check the DNF table
|
||||
check_kibom_test_netlist(rows[1], ref_column, 1, KIBOM_TEST_COMPONENTS, KIBOM_TEST_EXCLUDE)
|
||||
ctx.clean_up()
|
||||
|
|
@ -5,6 +5,7 @@ import logging
|
|||
import subprocess
|
||||
import re
|
||||
import pytest
|
||||
import csv
|
||||
from glob import glob
|
||||
from pty import openpty
|
||||
|
||||
|
|
@ -339,6 +340,41 @@ class TestContext(object):
|
|||
logging.debug("Found apertures {}".format(aps))
|
||||
return aps
|
||||
|
||||
def load_csv(self, filename, column=3):
|
||||
rows = []
|
||||
with open(self.expect_out_file(os.path.join(self.sub_dir, filename))) as csvfile:
|
||||
reader = csv.reader(csvfile)
|
||||
header = next(reader) # Skip header
|
||||
for r in reader:
|
||||
if not r:
|
||||
break
|
||||
rows.append(r)
|
||||
return rows, header
|
||||
|
||||
def load_html(self, filename, column=4, split=True):
|
||||
file = self.expect_out_file(os.path.join(self.sub_dir, filename))
|
||||
with open(file) as f:
|
||||
html = f.read()
|
||||
rows = [[], []]
|
||||
headers = [[], []]
|
||||
c = 0
|
||||
for body in re.findall(r'<table.*?>((?:\s+.*?)+)</table>', html, re.MULTILINE):
|
||||
if c:
|
||||
# Header
|
||||
m = re.search(r'<tr>\s+((?:<th.*?>(?:.*)</th>\s+)+)</tr>', body, re.MULTILINE)
|
||||
assert m, 'Failed to get table header'
|
||||
head = m.group(1)
|
||||
for col_name in re.findall(r'<th.*?>(.*)</th>', head):
|
||||
headers[c-1].append(col_name)
|
||||
# Rows
|
||||
for row in re.findall(r'<tr>\s+((?:<td.*?>(?:.*)</td>\s+)+)</tr>', body, re.MULTILINE):
|
||||
r = []
|
||||
for cell in re.findall(r'<td.*?>(.*?)</td>', row, re.MULTILINE):
|
||||
r.append(cell)
|
||||
rows[c-1].append(r)
|
||||
c += 1
|
||||
return rows, headers
|
||||
|
||||
|
||||
class TestContextSCH(TestContext):
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
# Example KiPlot config file
|
||||
kiplot:
|
||||
version: 1
|
||||
|
||||
outputs:
|
||||
- name: 'bom_internal'
|
||||
comment: "Bill of Materials in CSV format"
|
||||
type: bom
|
||||
dir: BoM
|
||||
options:
|
||||
format: CSV
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
# Example KiPlot config file
|
||||
kiplot:
|
||||
version: 1
|
||||
|
||||
outputs:
|
||||
- name: 'bom_internal'
|
||||
comment: "Bill of Materials in HTML format"
|
||||
type: bom
|
||||
dir: BoM
|
||||
options:
|
||||
format: HTML
|
||||
|
||||
Loading…
Reference in New Issue