From 3bfd99ad3db731ae6d37c615296fc74dfaa20396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Holger=20M=C3=BCller?= Date: Sat, 25 Jul 2020 21:34:49 +0200 Subject: [PATCH] Increased test coverage --- .coveragerc | 2 +- NanoVNASaver/Formatting.py | 4 +- NanoVNASaver/Settings/Sweep.py | 6 +- NanoVNASaver/Version.py | 133 -------------------------- NanoVNASaver/Windows/SweepSettings.py | 5 +- test/test_formatting.py | 27 ++++++ test/test_sweep.py | 42 ++++++++ test/test_version.py | 38 ++++++++ 8 files changed, 116 insertions(+), 141 deletions(-) create mode 100644 test/test_sweep.py create mode 100644 test/test_version.py diff --git a/.coveragerc b/.coveragerc index 7269f7e..6f64402 100644 --- a/.coveragerc +++ b/.coveragerc @@ -10,7 +10,7 @@ omit = NanoVNASaver/Inputs.py NanoVNASaver/Marker/*.py NanoVNASaver/NanoVNASaver.py - NanoVNASaver/Settings.py + NanoVNASaver/Settings/Bands.py NanoVNASaver/SweepWorker.py NanoVNASaver/Windows/*.py **/__init__.py diff --git a/NanoVNASaver/Formatting.py b/NanoVNASaver/Formatting.py index 2f04972..7c406f8 100644 --- a/NanoVNASaver/Formatting.py +++ b/NanoVNASaver/Formatting.py @@ -104,7 +104,7 @@ def format_group_delay(val: float) -> str: def format_phase(val: float) -> str: - return f"{math.degrees(val):.2f}\N{DEGREE SIGN}" + return f"{math.degrees(val):.2f}""\N{DEGREE SIGN}" def format_complex_imp(z: complex, allow_negative: bool = False) -> str: @@ -113,7 +113,7 @@ def format_complex_imp(z: complex, allow_negative: bool = False) -> str: fmt_re = FMT_COMPLEX_NEG re = SITools.Value(z.real, fmt=fmt_re) im = SITools.Value(abs(z.imag), fmt=FMT_COMPLEX) - return f"{re}{'-' if z.imag < 0 else '+'}j{im} \N{OHM SIGN}" + return f"{re}{'-' if z.imag < 0 else '+'}j{im} ""\N{OHM SIGN}" def format_wavelength(length: Number) -> str: return str(SITools.Value(length, "m", FMT_WAVELENGTH)) diff --git a/NanoVNASaver/Settings/Sweep.py b/NanoVNASaver/Settings/Sweep.py index 1a4e018..9884214 100644 --- a/NanoVNASaver/Settings/Sweep.py +++ b/NanoVNASaver/Settings/Sweep.py @@ -58,7 +58,7 @@ class Sweep(): def stepsize(self) -> int: return round(self.span / ((self.points -1) * self.segments)) - def _exp_factor(self, index: int) -> int: + def _exp_factor(self, index: int) -> float: return 1 - log(self.segments + 1 - index) / log(self.segments + 1) def get_index_range(self, index: int) -> Tuple[int, int]: @@ -66,8 +66,8 @@ class Sweep(): start = self.start + index * self.points * self.step end = start + (self.points - 1) * self.step else: - start = self.start + self.span * self._exp_factor(index) - end = self.start + self.span * self._exp_factor(index + 1) + start = round(self.start + self.span * self._exp_factor(index)) + end = round(self.start + self.span * self._exp_factor(index + 1)) logger.debug("get_index_range(%s) -> (%s, %s)", index, start, end) return (start, end) diff --git a/NanoVNASaver/Version.py b/NanoVNASaver/Version.py index 305429b..6fff530 100644 --- a/NanoVNASaver/Version.py +++ b/NanoVNASaver/Version.py @@ -1,5 +1,4 @@ # NanoVNASaver -# # A python program to view and export Touchstone data from a NanoVNA # Copyright (C) 2019, 2020 Rune B. Broberg # Copyright (C) 2020 NanoVNA-Saver Authors @@ -18,142 +17,10 @@ # along with this program. If not, see . import logging import re -import typing -from typing import List, Tuple - -from PyQt5 import QtCore, QtGui -from PyQt5.QtCore import QModelIndex logger = logging.getLogger(__name__) -class BandsModel(QtCore.QAbstractTableModel): - bands: List[Tuple[str, int, int]] = [] - enabled = False - color = QtGui.QColor(128, 128, 128, 48) - - # These bands correspond broadly to the Danish Amateur Radio allocation - default_bands = ["2200 m;135700;137800", - "630 m;472000;479000", - "160 m;1800000;2000000", - "80 m;3500000;3800000", - "60 m;5250000;5450000", - "40 m;7000000;7200000", - "30 m;10100000;10150000", - "20 m;14000000;14350000", - "17 m;18068000;18168000", - "15 m;21000000;21450000", - "12 m;24890000;24990000", - "10 m;28000000;29700000", - "6 m;50000000;52000000", - "4 m;69887500;70512500", - "2 m;144000000;146000000", - "70 cm;432000000;438000000", - "23 cm;1240000000;1300000000", - "13 cm;2320000000;2450000000"] - - def __init__(self): - super().__init__() - self.settings = QtCore.QSettings(QtCore.QSettings.IniFormat, - QtCore.QSettings.UserScope, - "NanoVNASaver", "Bands") - self.settings.setIniCodec("UTF-8") - self.enabled = self.settings.value("ShowBands", False, bool) - - stored_bands: List[str] = self.settings.value("bands", self.default_bands) - if stored_bands: - for b in stored_bands: - (name, start, end) = b.split(";") - self.bands.append((name, int(start), int(end))) - - def saveSettings(self): - stored_bands = [] - for b in self.bands: - stored_bands.append(b[0] + ";" + str(b[1]) + ";" + str(b[2])) - self.settings.setValue("bands", stored_bands) - self.settings.sync() - - def resetBands(self): - self.bands = [] - for b in self.default_bands: - (name, start, end) = b.split(";") - self.bands.append((name, int(start), int(end))) - self.layoutChanged.emit() - self.saveSettings() - - def columnCount(self, parent: QModelIndex = ...) -> int: - return 3 - - def rowCount(self, parent: QModelIndex = ...) -> int: - return len(self.bands) - - def data(self, index: QModelIndex, role: int = ...) -> QtCore.QVariant: - if (role == QtCore.Qt.DisplayRole or - role == QtCore.Qt.ItemDataRole or role == QtCore.Qt.EditRole): - return QtCore.QVariant(self.bands[index.row()][index.column()]) - if role == QtCore.Qt.TextAlignmentRole: - if index.column() == 0: - return QtCore.QVariant(QtCore.Qt.AlignCenter) - return QtCore.QVariant(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) - return QtCore.QVariant() - - def setData(self, index: QModelIndex, value: typing.Any, role: int = ...) -> bool: - if role == QtCore.Qt.EditRole and index.isValid(): - t = self.bands[index.row()] - name = t[0] - start = t[1] - end = t[2] - if index.column() == 0: - name = value - elif index.column() == 1: - start = value - elif index.column() == 2: - end = value - self.bands[index.row()] = (name, start, end) - self.dataChanged.emit(index, index) - self.saveSettings() - return True - return False - - def index(self, row: int, column: int, parent: QModelIndex = ...) -> QModelIndex: - return self.createIndex(row, column) - - def addRow(self): - self.bands.append(("New", 0, 0)) - self.dataChanged.emit(self.index(len(self.bands), 0), self.index(len(self.bands), 2)) - self.layoutChanged.emit() - - def removeRow(self, row: int, parent: QModelIndex = ...) -> bool: - self.bands.remove(self.bands[row]) - self.layoutChanged.emit() - self.saveSettings() - return True - - def headerData(self, section: int, - orientation: QtCore.Qt.Orientation, role: int = ...): - if (role == QtCore.Qt.DisplayRole and - orientation == QtCore.Qt.Horizontal): - if section == 0: - return "Band" - if section == 1: - return "Start (Hz)" - if section == 2: - return "End (Hz)" - return "Invalid" - super().headerData(section, orientation, role) - - def flags(self, index: QModelIndex) -> QtCore.Qt.ItemFlags: - if index.isValid(): - return QtCore.Qt.ItemFlags( - QtCore.Qt.ItemIsEditable | - QtCore.Qt.ItemIsEnabled | - QtCore.Qt.ItemIsSelectable) - super().flags(index) - - def setColor(self, color): - self.color = color - - class Version: RXP = re.compile(r"""^ \D* diff --git a/NanoVNASaver/Windows/SweepSettings.py b/NanoVNASaver/Windows/SweepSettings.py index 721324d..136fe04 100644 --- a/NanoVNASaver/Windows/SweepSettings.py +++ b/NanoVNASaver/Windows/SweepSettings.py @@ -77,7 +77,7 @@ class SweepSettingsWindow(QtWidgets.QWidget): "averages. Common values are 3/0, 5/2, 9/4 and 25/6.\n") label.setWordWrap(True) settings_layout.addRow(label) - + self.s21att = QtWidgets.QLineEdit("0") label = QtWidgets.QLabel( "Some times when you measure amplifiers you need to use an" @@ -88,7 +88,8 @@ class SweepSettingsWindow(QtWidgets.QWidget): settings_layout.addRow("Attenuator in port CH1 (s21) in dB", self.s21att) - # settings_layout.addRow(QtWidgets.QLabel("Common values with un-un are 16.9 (49:1 2450) 9.54 (9:1 450)")) + # settings_layout.addRow(QtWidgets.QLabel( + # "Common values with un-un are 16.9 (49:1 2450) 9.54 (9:1 450)")) self.continuous_sweep_radiobutton.toggled.connect( lambda: self.app.worker.setContinuousSweep( diff --git a/test/test_formatting.py b/test/test_formatting.py index 9bb8b75..86997b2 100644 --- a/test/test_formatting.py +++ b/test/test_formatting.py @@ -25,6 +25,15 @@ from NanoVNASaver import Formatting as fmt class TestCases(unittest.TestCase): def test_format_frequency(self): + self.assertEqual(fmt.format_frequency(1), '1.00000Hz') + self.assertEqual(fmt.format_frequency(12), '12.0000Hz') + self.assertEqual(fmt.format_frequency(123), '123.000Hz') + self.assertEqual(fmt.format_frequency(1234), '1.23400kHz') + self.assertEqual(fmt.format_frequency(1234567), '1.23457MHz') + self.assertEqual(fmt.format_frequency(1234567890), '1.23457GHz') + self.assertEqual(fmt.format_frequency(0), '0.00000Hz') + self.assertEqual(fmt.format_frequency(-1), '-1.00000Hz') + self.assertEqual(fmt.format_frequency_space(1), '1.00000 Hz') self.assertEqual(fmt.format_frequency_space(12), '12.0000 Hz') self.assertEqual(fmt.format_frequency_space(123), '123.000 Hz') @@ -34,6 +43,15 @@ class TestCases(unittest.TestCase): self.assertEqual(fmt.format_frequency_space(0), '0.00000 Hz') self.assertEqual(fmt.format_frequency_space(-1), '-1.00000 Hz') + self.assertEqual(fmt.format_frequency_short(1), '1.000Hz') + self.assertEqual(fmt.format_frequency_short(12), '12.00Hz') + self.assertEqual(fmt.format_frequency_short(123), '123.0Hz') + self.assertEqual(fmt.format_frequency_short(1234), '1.234kHz') + self.assertEqual(fmt.format_frequency_short(1234567), '1.235MHz') + self.assertEqual(fmt.format_frequency_short(1234567890), '1.235GHz') + self.assertEqual(fmt.format_frequency_short(0), '0.000Hz') + self.assertEqual(fmt.format_frequency_short(-1), '-1.000Hz') + def test_format_frequency_inputs(self): self.assertEqual(fmt.format_frequency_inputs(1), '1Hz') self.assertEqual(fmt.format_frequency_inputs(12), '12Hz') @@ -65,6 +83,11 @@ class TestCases(unittest.TestCase): self.assertEqual(fmt.format_vswr(1.234), '1.234') self.assertEqual(fmt.format_vswr(12345.12345), '12345.123') + def test_format_magnitude(self): + self.assertEqual(fmt.format_magnitude(1), '1.000') + self.assertEqual(fmt.format_magnitude(1.234), '1.234') + self.assertEqual(fmt.format_magnitude(12345.12345), '12345.123') + def test_format_resistance(self): self.assertEqual(fmt.format_resistance(1), '1 \N{OHM SIGN}') self.assertEqual(fmt.format_resistance(12), '12 \N{OHM SIGN}') @@ -112,3 +135,7 @@ class TestCases(unittest.TestCase): self.assertEqual(fmt.format_complex_imp(complex(1234, -1234)), '1.23k-j1.23k \N{OHM SIGN}') self.assertEqual(fmt.format_complex_imp(complex(1.234, 1234)), '1.23+j1.23k \N{OHM SIGN}') self.assertEqual(fmt.format_complex_imp(complex(-1, 1.23e-3)), '- +j1.23m \N{OHM SIGN}') + self.assertEqual(fmt.format_complex_imp(complex(-1, 1.23e-3), True), '-1+j1.23m \N{OHM SIGN}') + + def test_format_wavelength(self): + self.assertEqual(fmt.format_wavelength(12.3456), '12.35 m') diff --git a/test/test_sweep.py b/test/test_sweep.py new file mode 100644 index 0000000..912ddb4 --- /dev/null +++ b/test/test_sweep.py @@ -0,0 +1,42 @@ +# NanoVNASaver +# +# A python program to view and export Touchstone data from a NanoVNA +# Copyright (C) 2019, 2020 Rune B. Broberg +# Copyright (C) 2020 NanoVNA-Saver Authors +# +# 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 . +import unittest + +# Import targets to be tested +from NanoVNASaver.Settings import Sweep + +class TestCases(unittest.TestCase): + + def test_sweep(self): + sweep = Sweep() + self.assertEqual(str(sweep), 'Sweep(3600000, 30000000, 101, 1, False)') + self.assertTrue(Sweep(3600000) == sweep) + self.assertFalse(Sweep(3600001) == sweep) + self.assertRaises(ValueError, Sweep, -1) + sweep = Sweep(segments = 3) + self.assertEqual(sweep.get_index_range(1), (12488000, 21288000)) + data = list(sweep.get_frequencies()) + self.assertEqual(data[0], 3600000) + self.assertEqual(data[-1], 30000000) + sweep = Sweep(segments = 3, logarithmic=True) + self.assertEqual(sweep.get_index_range(1), (9078495, 16800000)) + data = list(sweep.get_frequencies()) + self.assertEqual(data[0], 3600000) + self.assertEqual(data[-1], 29869307) + diff --git a/test/test_version.py b/test/test_version.py new file mode 100644 index 0000000..17312ab --- /dev/null +++ b/test/test_version.py @@ -0,0 +1,38 @@ +# NanoVNASaver +# +# A python program to view and export Touchstone data from a NanoVNA +# Copyright (C) 2019, 2020 Rune B. Broberg +# Copyright (C) 2020 NanoVNA-Saver Authors +# +# 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 . +import unittest + +# Import targets to be tested +from NanoVNASaver.Version import Version + +class TestCases(unittest.TestCase): + + def test_version(self): + ver = Version("v1.2.3-test") + self.assertEqual(str(ver), '1.2.3-test') + self.assertLessEqual(ver, Version("1.2.4")) + self.assertFalse(ver > Version("1.2.4")) + self.assertFalse(ver > Version("1.2.3-u")) + self.assertTrue(Version("1.2.4") >= ver) + self.assertFalse(Version("0.0.0") == Version("0.0.0-rc")) + self.assertEqual(ver.major, 1) + self.assertEqual(ver.minor, 2) + self.assertEqual(ver.revision, 3) + self.assertEqual(ver.note, '-test') + Version("asdasd")