diff --git a/.coveragerc b/.coveragerc index 5c70a1a..85bf3bb 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,2 +1,2 @@ [run] -omit = meshtastic/*_pb2.py,meshtastic/test.py +omit = meshtastic/*_pb2.py,meshtastic/test.py,meshtastic/test/*.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4985df3..3acf7de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,6 @@ jobs: which meshtastic meshtastic --version - name: Run pylint - run: pylint --exit-zero meshtastic + run: pylint meshtastic - name: Run tests with pytest run: pytest --cov=meshtastic diff --git a/meshtastic/serial_interface.py b/meshtastic/serial_interface.py index 4f8ddf3..90b6922 100644 --- a/meshtastic/serial_interface.py +++ b/meshtastic/serial_interface.py @@ -6,8 +6,8 @@ import os import stat import serial +import meshtastic.util from .stream_interface import StreamInterface -from .util import findPorts, our_exit class SerialInterface(StreamInterface): """Interface class for meshtastic devices over a serial link""" @@ -22,14 +22,14 @@ class SerialInterface(StreamInterface): """ if devPath is None: - ports = findPorts() + ports = meshtastic.util.findPorts() logging.debug(f"ports:{ports}") if len(ports) == 0: - our_exit("Warning: No Meshtastic devices detected.") + meshtastic.util.our_exit("Warning: No Meshtastic devices detected.") elif len(ports) > 1: message = "Warning: Multiple serial ports were detected so one serial port must be specified with the '--port'.\n" message += f" Ports detected:{ports}" - our_exit(message) + meshtastic.util.our_exit(message) else: devPath = ports[0] diff --git a/meshtastic/test/test_mesh_interface.py b/meshtastic/test/test_mesh_interface.py index 77a5608..325c17a 100644 --- a/meshtastic/test/test_mesh_interface.py +++ b/meshtastic/test/test_mesh_interface.py @@ -1,15 +1,15 @@ -"""Meshtastic unit tests for node.py""" +"""Meshtastic unit tests for mesh_interface.py""" import re import pytest -from meshtastic.mesh_interface import MeshInterface +from ..mesh_interface import MeshInterface @pytest.mark.unit def test_MeshInterface(capsys): - """Test that we instantiate a MeshInterface""" + """Test that we can instantiate a MeshInterface""" iface = MeshInterface(noProto=True) iface.showInfo() iface.localNode.showInfo() diff --git a/meshtastic/test/test_serial_interface.py b/meshtastic/test/test_serial_interface.py new file mode 100644 index 0000000..10b4dbc --- /dev/null +++ b/meshtastic/test/test_serial_interface.py @@ -0,0 +1,49 @@ +"""Meshtastic unit tests for serial_interface.py""" + +import re + + +from unittest.mock import patch +import pytest + +from ..serial_interface import SerialInterface + +@pytest.mark.unit +@patch('serial.Serial') +@patch('meshtastic.util.findPorts', return_value=['/dev/ttyUSBfake']) +def test_SerialInterface_single_port(mocked_findPorts, mocked_serial): + """Test that we can instantiate a SerialInterface with a single port""" + iface = SerialInterface(noProto=True) + iface.showInfo() + iface.localNode.showInfo() + iface.close() + mocked_findPorts.assert_called() + mocked_serial.assert_called() + + +@pytest.mark.unit +@patch('meshtastic.util.findPorts', return_value=[]) +def test_SerialInterface_no_ports(mocked_findPorts, capsys): + """Test that we can instantiate a SerialInterface with no ports""" + with pytest.raises(SystemExit) as pytest_wrapped_e: + SerialInterface(noProto=True) + mocked_findPorts.assert_called() + assert pytest_wrapped_e.type == SystemExit + assert pytest_wrapped_e.value.code == 1 + out, err = capsys.readouterr() + assert re.search(r'Warning: No Meshtastic devices detected', out, re.MULTILINE) + assert err == '' + + +@pytest.mark.unit +@patch('meshtastic.util.findPorts', return_value=['/dev/ttyUSBfake1', '/dev/ttyUSBfake2']) +def test_SerialInterface_multiple_ports(mocked_findPorts, capsys): + """Test that we can instantiate a SerialInterface with two ports""" + with pytest.raises(SystemExit) as pytest_wrapped_e: + SerialInterface(noProto=True) + mocked_findPorts.assert_called() + assert pytest_wrapped_e.type == SystemExit + assert pytest_wrapped_e.value.code == 1 + out, err = capsys.readouterr() + assert re.search(r'Warning: Multiple serial ports were detected', out, re.MULTILINE) + assert err == '' diff --git a/meshtastic/test/test_smoke1.py b/meshtastic/test/test_smoke1.py index 242604f..a7f4b00 100644 --- a/meshtastic/test/test_smoke1.py +++ b/meshtastic/test/test_smoke1.py @@ -8,7 +8,7 @@ import os # sense to pause for the radio at apprpriate times import pytest -import meshtastic +from ..util import findPorts # seconds to pause after running a meshtastic command PAUSE_AFTER_COMMAND = 2 @@ -143,7 +143,7 @@ def test_smoke1_send_hello(): def test_smoke1_port(): """Test --port""" # first, get the ports - ports = meshtastic.util.findPorts() + ports = findPorts() # hopefully there is just one assert len(ports) == 1 port = ports[0] diff --git a/meshtastic/test/test_stream_interface.py b/meshtastic/test/test_stream_interface.py new file mode 100644 index 0000000..57c65d2 --- /dev/null +++ b/meshtastic/test/test_stream_interface.py @@ -0,0 +1,14 @@ +"""Meshtastic unit tests for stream_interface.py""" + + +import pytest + +from ..stream_interface import StreamInterface + + +@pytest.mark.unit +def test_StreamInterface(): + """Test that we can instantiate a StreamInterface""" + with pytest.raises(Exception) as pytest_wrapped_e: + StreamInterface(noProto=True) + assert pytest_wrapped_e.type == Exception diff --git a/meshtastic/test/test_tcp_interface.py b/meshtastic/test/test_tcp_interface.py new file mode 100644 index 0000000..432caef --- /dev/null +++ b/meshtastic/test/test_tcp_interface.py @@ -0,0 +1,26 @@ +"""Meshtastic unit tests for tcp_interface.py""" + +import re + +from unittest.mock import patch +import pytest + +from ..tcp_interface import TCPInterface + + +@pytest.mark.unit +def test_TCPInterface(capsys): + """Test that we can instantiate a TCPInterface""" + with patch('socket.socket') as mock_socket: + iface = TCPInterface(hostname='localhost', noProto=True) + iface.showInfo() + iface.localNode.showInfo() + out, err = capsys.readouterr() + assert re.search(r'Owner: None \(None\)', out, re.MULTILINE) + assert re.search(r'Nodes', out, re.MULTILINE) + assert re.search(r'Preferences', out, re.MULTILINE) + assert re.search(r'Channels', out, re.MULTILINE) + assert re.search(r'Primary channel URL', out, re.MULTILINE) + assert err == '' + assert mock_socket.called + iface.close() diff --git a/meshtastic/test/test_util.py b/meshtastic/test/test_util.py index ea3253b..cf5f638 100644 --- a/meshtastic/test/test_util.py +++ b/meshtastic/test/test_util.py @@ -1,4 +1,4 @@ -"""Meshtastic unit tests for node.py""" +"""Meshtastic unit tests for util.py""" import re