kopia lustrzana https://github.com/NanoVNA-Saver/nanovna-saver
Add unittest framework
Adding a unittest framework to the project to enhance debugging capabilities, document expected (and unexpected) behaviors, and to prevent regression failures.pull/95/head
rodzic
0b73e89d51
commit
2f9749bd60
|
@ -0,0 +1,16 @@
|
|||
# NanoVNASaver - a python program to view and export Touchstone data from a NanoVNA
|
||||
# Copyright (C) 2019. Rune B. Broberg
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
# NanoVNASaver - a python program to view and export Touchstone data from a NanoVNA
|
||||
# Copyright (C) 2019. Rune B. Broberg
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
# Import targets to be tested
|
||||
from NanoVNASaver import RFTools
|
||||
rft = RFTools.RFTools()
|
||||
|
||||
class TestCases(unittest.TestCase):
|
||||
|
||||
'''
|
||||
def formatSweepFrequency(freq: int,
|
||||
mindigits: int = 2,
|
||||
appendHz: bool = True,
|
||||
insertSpace: bool = False,
|
||||
countDot: bool = True,
|
||||
assumeInfinity: bool = True) -> str:
|
||||
'''
|
||||
|
||||
def test_basicIntegerValues(self):
|
||||
# simple well-formed integers with no trailing zeros. Most importantly
|
||||
# even with default mindigits, there is no loss of accuracy in the
|
||||
# result. Returned values are not truncated if result would lose
|
||||
# meaningful data.
|
||||
self.assertEqual(rft.formatSweepFrequency(1), '1Hz')
|
||||
self.assertEqual(rft.formatSweepFrequency(12), '12Hz')
|
||||
self.assertEqual(rft.formatSweepFrequency(123), '123Hz')
|
||||
self.assertEqual(rft.formatSweepFrequency(1234), '1.234kHz')
|
||||
self.assertEqual(rft.formatSweepFrequency(12345), '12.345kHz')
|
||||
self.assertEqual(rft.formatSweepFrequency(123456), '123.456kHz')
|
||||
self.assertEqual(rft.formatSweepFrequency(1234567), '1.234567MHz')
|
||||
self.assertEqual(rft.formatSweepFrequency(12345678), '12.345678MHz')
|
||||
self.assertEqual(rft.formatSweepFrequency(123456789), '123.456789MHz')
|
||||
|
||||
def test_defaultMinDigits(self):
|
||||
# simple integers with trailing zeros.
|
||||
# DEFAULT behavior retains 2 digits after the period, mindigits=2.
|
||||
self.assertEqual(rft.formatSweepFrequency(1000), '1.00kHz')
|
||||
self.assertEqual(rft.formatSweepFrequency(10000), '10.00kHz')
|
||||
self.assertEqual(rft.formatSweepFrequency(100000), '100.00kHz')
|
||||
self.assertEqual(rft.formatSweepFrequency(1000000), '1.00MHz')
|
||||
|
||||
def test_nonDefaultMinDigits(self):
|
||||
# simple integers with trailing zeros. setting mindigit value to something
|
||||
# other than default, where trailing zeros >= mindigits, the number of
|
||||
# zeros shown is equal to mindigits value.
|
||||
self.assertEqual(rft.formatSweepFrequency(1000000, mindigits=0), '1MHz')
|
||||
self.assertEqual(rft.formatSweepFrequency(1000000, mindigits=1), '1.0MHz')
|
||||
self.assertEqual(rft.formatSweepFrequency(1000000, mindigits=3), '1.000MHz')
|
||||
self.assertEqual(rft.formatSweepFrequency(10000000, mindigits=4), '10.0000MHz')
|
||||
self.assertEqual(rft.formatSweepFrequency(100000000, mindigits=5), '100.00000MHz')
|
||||
self.assertEqual(rft.formatSweepFrequency(1000000000, mindigits=6), '1.000000GHz')
|
||||
# where trailing zeros < mindigits, only available zeros are shown, if the
|
||||
# result includes no decimal places (i.e. Hz values).
|
||||
self.assertEqual(rft.formatSweepFrequency(1, mindigits=4), '1Hz')
|
||||
self.assertEqual(rft.formatSweepFrequency(10, mindigits=4), '10Hz')
|
||||
self.assertEqual(rft.formatSweepFrequency(100, mindigits=4), '100Hz')
|
||||
# but where a decimal exists, and mindigits > number of available zeroes,
|
||||
# this results in extra zeroes being padded into result, even into sub-Hz
|
||||
# resolution. This is not useful for this application.
|
||||
# TODO: Consider post-processing result for maxdigits based on SI unit.
|
||||
self.assertEqual(rft.formatSweepFrequency(1000, mindigits=5), '1.00000kHz')
|
||||
self.assertEqual(rft.formatSweepFrequency(1000, mindigits=10), '1.0000000000kHz')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
|
@ -0,0 +1,141 @@
|
|||
# NanoVNASaver - a python program to view and export Touchstone data from a NanoVNA
|
||||
# Copyright (C) 2019. Rune B. Broberg
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
# Import targets to be tested
|
||||
from NanoVNASaver import RFTools
|
||||
rft = RFTools.RFTools()
|
||||
|
||||
class TestCases(unittest.TestCase):
|
||||
|
||||
def test_basicSIUnits(self):
|
||||
# simple well-formed integers with correct SI units
|
||||
self.assertEqual(rft.parseFrequency('123Hz'), 123)
|
||||
self.assertEqual(rft.parseFrequency('123456Hz'), 123456)
|
||||
self.assertEqual(rft.parseFrequency('123kHz'), 123000)
|
||||
self.assertEqual(rft.parseFrequency('123456kHz'), 123456000)
|
||||
self.assertEqual(rft.parseFrequency('123MHz'), 123000000)
|
||||
self.assertEqual(rft.parseFrequency('123456MHz'), 123456000000)
|
||||
self.assertEqual(rft.parseFrequency('123GHz'), 123000000000)
|
||||
self.assertEqual(rft.parseFrequency('123456GHz'), 123456000000000)
|
||||
|
||||
def test_commonMistakeKHz_vs_kHz(self):
|
||||
# some poorly formatted values that still work as expected
|
||||
self.assertEqual(rft.parseFrequency('123kHz'), 123000)
|
||||
self.assertEqual(rft.parseFrequency('123KHz'), 123000)
|
||||
|
||||
def test_illegalInputValues(self):
|
||||
# poorly formatted inputs that are identified as illegal
|
||||
self.assertEqual(rft.parseFrequency('Junk'), -1)
|
||||
self.assertEqual(rft.parseFrequency('Garbage'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123.Junk'), -1)
|
||||
|
||||
def test_missingDigitsAfterPeriod(self):
|
||||
# some poorly formatted values that still work as expected
|
||||
self.assertEqual(rft.parseFrequency('123.'), 123)
|
||||
self.assertEqual(rft.parseFrequency('123.Hz'), 123)
|
||||
self.assertEqual(rft.parseFrequency('123.kHz'), 123000)
|
||||
self.assertEqual(rft.parseFrequency('123.MHz'), 123000000)
|
||||
self.assertEqual(rft.parseFrequency('123.GHz'), 123000000000)
|
||||
|
||||
def test_unusualSIUnits(self):
|
||||
#######################################################################
|
||||
# Original behavior: unusual SI values that were legal, but inappropriate
|
||||
# for this application provided unexpected outputs. This behavior was
|
||||
# based on the full set of SI prefixes previously defined in SITools (below).
|
||||
#PREFIXES = ("y", "z", "a", "f", "p", "n", "µ", "m",
|
||||
# "", "k", "M", "G", "T", "P", "E", "Z", "Y")
|
||||
# New Behavior: After the reduction of legal SI values defined in SITools
|
||||
# (below), these now return a -1 failure code.
|
||||
# PREFIXES = ("", "k", "M", "G")
|
||||
#######################################################################
|
||||
'''
|
||||
self.assertEqual(rft.parseFrequency('123EHz'), 123000000000000000000)
|
||||
self.assertEqual(rft.parseFrequency('123PHz'), 123000000000000000)
|
||||
self.assertEqual(rft.parseFrequency('123THz'), 123000000000000)
|
||||
self.assertEqual(rft.parseFrequency('123YHz'), 122999999999999998473273344)
|
||||
self.assertEqual(rft.parseFrequency('123ZHz'), 123000000000000002097152)
|
||||
self.assertEqual(rft.parseFrequency('123aHz'), 0)
|
||||
self.assertEqual(rft.parseFrequency('123fHz'), 0)
|
||||
self.assertEqual(rft.parseFrequency('123mHz'), 0)
|
||||
self.assertEqual(rft.parseFrequency('123nHz'), 0)
|
||||
self.assertEqual(rft.parseFrequency('123pHz'), 0)
|
||||
self.assertEqual(rft.parseFrequency('123yHz'), 0)
|
||||
self.assertEqual(rft.parseFrequency('123zHz'), 0)
|
||||
'''
|
||||
self.assertEqual(rft.parseFrequency('123EHz'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123PHz'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123THz'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123YHz'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123ZHz'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123aHz'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123fHz'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123mHz'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123nHz'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123pHz'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123yHz'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123zHz'), -1)
|
||||
|
||||
def test_partialHzText(self):
|
||||
#######################################################################
|
||||
# Previous behavior for accidentally missing the H in Hz, resulted in
|
||||
# detection of 'z' SI unit (zepto = 10^-21), which then rounded to 0.
|
||||
# After reduction of legal SI values in SITools, this now returns a -1
|
||||
# failure code.
|
||||
#######################################################################
|
||||
'''
|
||||
self.assertEqual(rft.parseFrequency('123z'), 0)
|
||||
self.assertEqual(rft.parseFrequency('123.z'), 0)
|
||||
self.assertEqual(rft.parseFrequency('1.23z'), 0)
|
||||
'''
|
||||
self.assertEqual(rft.parseFrequency('123z'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123.z'), -1)
|
||||
self.assertEqual(rft.parseFrequency('1.23z'), -1)
|
||||
|
||||
def test_basicExponentialNotation(self):
|
||||
# check basic exponential notation
|
||||
self.assertEqual(rft.parseFrequency('123e3'), 123000)
|
||||
self.assertEqual(rft.parseFrequency('123e6'), 123000000)
|
||||
self.assertEqual(rft.parseFrequency('123e9'), 123000000000)
|
||||
self.assertEqual(rft.parseFrequency('123e4'), 1230000)
|
||||
self.assertEqual(rft.parseFrequency('123e12'), 123000000000000)
|
||||
self.assertEqual(rft.parseFrequency('123e18'), 123000000000000000000)
|
||||
|
||||
def test_negativeExponentialNotation(self):
|
||||
# negative exponential values resulting in N < 0, return 0
|
||||
self.assertEqual(rft.parseFrequency('123e-3'), 0)
|
||||
self.assertEqual(rft.parseFrequency('1234e-4'), 0)
|
||||
self.assertEqual(rft.parseFrequency('12345e-5'), 0)
|
||||
self.assertEqual(rft.parseFrequency('12345678e-8'), 0)
|
||||
# negative exponential values resulting in N > 0, return N
|
||||
self.assertEqual(rft.parseFrequency('100000e-5'), 1)
|
||||
self.assertEqual(rft.parseFrequency('100000e-4'), 10)
|
||||
self.assertEqual(rft.parseFrequency('100000e-3'), 100)
|
||||
self.assertEqual(rft.parseFrequency('100000e-2'), 1000)
|
||||
self.assertEqual(rft.parseFrequency('100000e-1'), 10000)
|
||||
|
||||
def test_multiplePeriods(self):
|
||||
# multiple periods are properly detected as bad
|
||||
self.assertEqual(rft.parseFrequency('123..Hz'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123...Hz'), -1)
|
||||
self.assertEqual(rft.parseFrequency('123....Hz'), -1)
|
||||
self.assertEqual(rft.parseFrequency('1.23.Hz'), -1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
|
@ -0,0 +1,37 @@
|
|||
# NanoVNASaver - a python program to view and export Touchstone data from a NanoVNA
|
||||
# Copyright (C) 2019. Rune B. Broberg
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Executing this file initiates the discovery and execution of all unittests
|
||||
# in the "test" directory, with filenames starting with "test" that have a
|
||||
# TestCases(unittest.TestCase) Class, which has class functions starting with
|
||||
# "test_". This provides a simple test framework that is easily expandable by
|
||||
# simply adding new "test_xxx.py" files into the test directory.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
if __name__ == '__main__':
|
||||
loader = unittest.TestLoader()
|
||||
tests = loader.discover('.')
|
||||
testRunner = unittest.runner.TextTestRunner(
|
||||
failfast=False,
|
||||
verbosity=2)
|
||||
testRunner.run(tests)
|
Ładowanie…
Reference in New Issue