Skip to content

Commit 66bd765

Browse files
committed
bringing unit tests up to 90%
1 parent dd6a08b commit 66bd765

File tree

10 files changed

+171
-42
lines changed

10 files changed

+171
-42
lines changed

doc/current.coverage

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
11
Name Stmts Exec Cover Missing
22
---------------------------------------------------------------
33
pymodbus 9 9 100%
4-
pymodbus.bit_read_message 64 64 100%
5-
pymodbus.bit_write_message 88 62 70% 73-81, 88, 129, 157, 174-176, 184-192, 199, 230, 237
4+
pymodbus.bit_read_message 65 65 100%
5+
pymodbus.bit_write_message 92 68 73% 74-82, 89, 130, 154, 184-193, 200-201, 232, 239
66
pymodbus.client 1 1 100%
7-
pymodbus.client.async 86 32 37% 55-61, 67-72, 77-78, 87-90, 104-105, 112-113, 121-124, 130, 160-172, 183, 190-194, 201, 214-226
7+
pymodbus.client.async 44 22 50% 49-51, 56-57, 62-63, 70, 76-80, 88-89, 97-102, 113-116
8+
pymodbus.client.common 35 35 100%
89
pymodbus.constants 18 18 100%
9-
pymodbus.datastore 99 60 60% 81-82, 86, 95, 104, 112, 119, 126-128, 141, 152-154, 163-164, 172-173, 186-192, 201-202, 211, 219-220, 260, 264-265, 275-276, 286-287, 296-297
10-
pymodbus.device 112 112 100%
11-
pymodbus.diag_message 183 168 91% 49, 62, 104, 131, 165-168, 175, 190-193, 212, 242
10+
pymodbus.datastore 109 65 59% 82-83, 87, 96, 105, 113, 120, 127-129, 142, 153-155, 164-165, 173-174, 187-193, 202-203, 212, 220-221, 261, 265-266, 276-277, 287-288, 297-298, 311, 321, 330, 337, 375
11+
pymodbus.device 128 128 100%
12+
pymodbus.diag_message 183 168 91% 49, 62, 104, 131, 165-168, 175, 190-193, 216, 246
13+
pymodbus.events 58 29 50% 20, 27, 70-73, 100-105, 112-116, 124-130, 146, 153-154, 180, 187-188
1214
pymodbus.exceptions 22 22 100%
13-
pymodbus.factory 52 46 88% 56-58, 107-109
15+
pymodbus.factory 52 52 100%
1416
pymodbus.file_message 36 33 91% 45, 52, 62
15-
pymodbus.interfaces 31 21 67% 36, 56, 70, 78, 88, 98, 105, 115, 132, 143
16-
pymodbus.other_message 73 40 54% 29, 34, 41, 48-49, 66-67, 74, 81, 111, 116, 123, 130-131, 148-150, 157-158, 165-166, 186, 191, 198, 205-206, 221-223, 230-231, 238-239
17+
pymodbus.interfaces 36 36 100%
18+
pymodbus.internal 1 1 100%
19+
pymodbus.other_message 129 60 46% 30, 35, 42, 49-50, 57, 74-75, 82, 89, 96-97, 127, 132, 139, 146-147, 154, 171-173, 180-181, 188-189, 196-197, 226, 231, 238, 245-251, 258, 277-281, 288-293, 300-308, 315-316, 331, 336, 343, 350-351, 358, 373-375, 382-383, 390-391, 398-399
1720
pymodbus.pdu 58 58 100%
18-
pymodbus.register_read_message 119 93 78% 45, 86, 93, 124-125, 172-173, 223, 244-249, 262-270, 277, 311-313, 320
19-
pymodbus.register_write_message 79 54 68% 51-57, 64, 102, 128, 146-148, 156-164, 171, 202, 209
21+
pymodbus.register_read_message 120 94 78% 45, 86, 93, 124-125, 172-173, 244-249, 262-270, 277-278, 311-313, 320
22+
pymodbus.register_write_message 86 58 67% 52-59, 66, 104-105, 151-154, 162-171, 178-179, 210, 217-218
2023
pymodbus.server 0 0 100%
21-
pymodbus.transaction 218 130 59% 48-60, 225-235, 315-316, 334, 341, 371-380, 387-392, 510-519, 566-570, 580-593, 601-602, 611, 620, 627, 637, 657-666, 674-679, 690-692
22-
pymodbus.utilities 53 53 100%
24+
pymodbus.transaction 231 140 60% 49-61, 226-236, 317-318, 336, 343-346, 376-385, 392-397, 518-527, 578-582, 592-605, 613-614, 623, 632, 639, 649, 669-678, 686-691, 702-704
25+
pymodbus.utilities 63 63 100%
2326
pymodbus.version 4 4 100%
2427
---------------------------------------------------------------
25-
TOTAL 1405 1080 76%
28+
TOTAL 1580 1229 77%
2629
----------------------------------------------------------------------
27-
Ran 85 tests in 0.136s
30+
Ran 95 tests in 0.158s
2831

2932
OK

pymodbus/bit_write_message.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ def __init__(self, address=None, values=None):
152152
self.address = address
153153
if not values:
154154
raise ParameterException('No values specified to write')
155+
elif not hasattr(values, '__iter__'): values = [values]
155156
self.values = values
156157

157158
def encode(self):

pymodbus/client/sync.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,10 @@ class ModbusTcpClient(BaseModbusClient):
180180
''' Implementation of a modbus tcp client
181181
'''
182182

183-
def __init__(self, host, port=Defaults.Port):
183+
def __init__(self, host='127.0.0.1', port=Defaults.Port):
184184
''' Initialize a client instance
185185
186-
:param host: The host to connect to
186+
:param host: The host to connect to (default 127.0.0.1)
187187
:param port: The modbus port to connect to (default 502)
188188
'''
189189
self.host = host
@@ -247,10 +247,10 @@ class ModbusUdpClient(BaseModbusClient):
247247
''' Implementation of a modbus udp client
248248
'''
249249

250-
def __init__(self, host, port=Defaults.Port):
250+
def __init__(self, host='127.0.0.1', port=Defaults.Port):
251251
''' Initialize a client instance
252252
253-
:param host: The host to connect to
253+
:param host: The host to connect to (default 127.0.0.1)
254254
:param port: The modbus port to connect to (default 502)
255255
'''
256256
self.host = host

pymodbus/interfaces.py

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,6 @@ def __new__(cls, *args, **kwargs):
2222
cls._inst = object.__new__(cls, *args, **kwargs)
2323
return cls._inst
2424

25-
class Borg(object):
26-
'''
27-
Borg base class
28-
http://code.activestate.com/recipes/66531/
29-
'''
30-
__shared_state = {}
31-
32-
def __init__(self):
33-
''' Initialize the new instance
34-
Make sure this __init__ is called in the child class
35-
'''
36-
self.__dict__ = self.__shared_state
37-
3825
#---------------------------------------------------------------------------#
3926
# Project Specific
4027
#---------------------------------------------------------------------------#
@@ -189,6 +176,6 @@ def setValues(self, fx, address, values):
189176
# Exported symbols
190177
#---------------------------------------------------------------------------#
191178
__all__ = [
192-
'Singleton', 'Borg',
193-
'IModbusDecoder', 'IModbusFramer',
179+
'Singleton',
180+
'IModbusDecoder', 'IModbusFramer', 'IModbusSlaveContext',
194181
]

pymodbus/register_write_message.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ def __init__(self, address=None, values=None):
128128
self.address = address
129129
if not values:
130130
raise ParameterException('No values specified to write')
131+
elif not hasattr(values, '__iter__'): values = [values]
131132
self.values = values
132133

133134
def encode(self):

test/test_bit_messages.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#---------------------------------------------------------------------------#
1919
# Mocks
2020
#---------------------------------------------------------------------------#
21-
class Context:
21+
class Context(object):
2222
def validate(self, a,b,c):
2323
return False
2424

test/test_client_common.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import unittest
2+
from pymodbus.client.common import ModbusClientMixin
3+
from pymodbus.bit_read_message import *
4+
from pymodbus.bit_write_message import *
5+
from pymodbus.register_read_message import *
6+
from pymodbus.register_write_message import *
7+
8+
#---------------------------------------------------------------------------#
9+
# Mocks
10+
#---------------------------------------------------------------------------#
11+
class MockClient(ModbusClientMixin):
12+
13+
def execute(self, request):
14+
return request
15+
16+
#---------------------------------------------------------------------------#
17+
# Fixture
18+
#---------------------------------------------------------------------------#
19+
class ModbusCommonClientTests(unittest.TestCase):
20+
21+
#-----------------------------------------------------------------------#
22+
# Setup/TearDown
23+
#-----------------------------------------------------------------------#
24+
def setUp(self):
25+
'''
26+
Initializes the test environment and builds request/result
27+
encoding pairs
28+
'''
29+
self.client = MockClient()
30+
31+
def tearDown(self):
32+
''' Cleans up the test environment '''
33+
del self.client
34+
35+
#-----------------------------------------------------------------------#
36+
# Tests
37+
#-----------------------------------------------------------------------#
38+
def testModbusClientMixinMethods(self):
39+
''' This tests that the mixing returns the correct request object '''
40+
self.assertTrue(isinstance(self.client.read_coils(1,1), ReadCoilsRequest))
41+
self.assertTrue(isinstance(self.client.read_discrete_inputs(1,1), ReadDiscreteInputsRequest))
42+
self.assertTrue(isinstance(self.client.write_coil(1,True), WriteSingleCoilRequest))
43+
self.assertTrue(isinstance(self.client.write_coils(1,[True]), WriteMultipleCoilsRequest))
44+
self.assertTrue(isinstance(self.client.write_register(1,0x00), WriteSingleRegisterRequest))
45+
self.assertTrue(isinstance(self.client.write_registers(1,[0x00]), WriteMultipleRegistersRequest))
46+
self.assertTrue(isinstance(self.client.read_holding_registers(1,1), ReadHoldingRegistersRequest))
47+
self.assertTrue(isinstance(self.client.read_input_registers(1,1), ReadInputRegistersRequest))
48+
self.assertTrue(isinstance(self.client.readwrite_registers(1,1), ReadWriteMultipleRegistersRequest))

test/test_factory.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import unittest
22
from pymodbus.factory import ServerDecoder, ClientDecoder
3-
from pymodbus.exceptions import *
3+
from pymodbus.exceptions import ModbusException
4+
5+
def _raise_exception(_):
6+
raise ModbusException('something')
47

58
class SimpleFactoryTest(unittest.TestCase):
69
'''
@@ -88,15 +91,15 @@ def testRequestsWorking(self):
8891

8992
def testClientFactoryFails(self):
9093
''' Tests that a client factory will fail to decode a bad message '''
91-
pass
92-
# actual = self.client.decode(None)
93-
# self.assertEquals(actual, None)
94+
self.client._helper = _raise_exception
95+
actual = self.client.decode(None)
96+
self.assertEquals(actual, None)
9497

9598
def testServerFactoryFails(self):
9699
''' Tests that a server factory will fail to decode a bad message '''
97-
pass
98-
# actual = self.server.decode(None)
99-
# self.assertEquals(actual, None)
100+
self.server._helper = _raise_exception
101+
actual = self.server.decode(None)
102+
self.assertEquals(actual, None)
100103

101104
#---------------------------------------------------------------------------#
102105
# I don't actually know what is supposed to be returned here, I assume that

test/test_interfaces.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import unittest
2+
from pymodbus.interfaces import *
3+
from pymodbus.exceptions import NotImplementedException
4+
5+
class _SingleInstance(Singleton):
6+
pass
7+
8+
class ModbusInterfaceTestsTest(unittest.TestCase):
9+
'''
10+
This is the unittest for the pymodbus.interfaces module
11+
'''
12+
13+
def setUp(self):
14+
''' Initializes the test environment '''
15+
pass
16+
17+
def tearDown(self):
18+
''' Cleans up the test environment '''
19+
pass
20+
21+
def testSingletonInterface(self):
22+
''' Test that the singleton interface works '''
23+
first = _SingleInstance()
24+
second = _SingleInstance()
25+
self.assertEquals(first, second)
26+
27+
def testModbusDecoderInterface(self):
28+
''' Test that the base class isn't implemented '''
29+
x = None
30+
instance = IModbusDecoder()
31+
self.assertRaises(NotImplementedException, lambda: instance.decode(x))
32+
33+
def testModbusFramerInterface(self):
34+
''' Test that the base class isn't implemented '''
35+
x = None
36+
instance = IModbusFramer()
37+
self.assertRaises(NotImplementedException, instance.checkFrame)
38+
self.assertRaises(NotImplementedException, instance.advanceFrame)
39+
self.assertRaises(NotImplementedException, instance.isFrameReady)
40+
self.assertRaises(NotImplementedException, instance.getFrame)
41+
self.assertRaises(NotImplementedException, lambda: instance.addToFrame(x))
42+
self.assertRaises(NotImplementedException, lambda: instance.populateResult(x))
43+
self.assertRaises(NotImplementedException, lambda: instance.processIncomingPacket(x,x))
44+
self.assertRaises(NotImplementedException, lambda: instance.buildPacket(x))
45+
46+
def testModbusSlaveContextInterface(self):
47+
''' Test that the base class isn't implemented '''
48+
x = None
49+
instance = IModbusSlaveContext()
50+
self.assertRaises(NotImplementedException, instance.reset)
51+
self.assertRaises(NotImplementedException, lambda: instance.validate(x,x,x))
52+
self.assertRaises(NotImplementedException, lambda: instance.getValues(x,x,x))
53+
self.assertRaises(NotImplementedException, lambda: instance.setValues(x,x,x))
54+
55+
#---------------------------------------------------------------------------#
56+
# Main
57+
#---------------------------------------------------------------------------#
58+
if __name__ == "__main__":
59+
unittest.main()

tools/reference/virtual-serial.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <stdlib.h>
2+
#include <stdio.h>
3+
#include <fcntl.h>
4+
5+
int main(int argc, char *argv[])
6+
{
7+
char *buffer = calloc(256, sizeof(char));
8+
9+
int pt = open("/dev/ptmx", O_RDWR | O_NOCTTY);
10+
if (pt < 0) {
11+
perror("open /dev/ptmx");
12+
return -1;
13+
}
14+
grantpt(pt);
15+
unlockpt(pt);
16+
fprintf(stderr, "Slave Device: %s\n", (char *)ptsname(pt));
17+
18+
while(1) {
19+
int size = read(pt, buffer, 256);
20+
if (size > 0) {
21+
fprintf(stderr, "%s", buffer);
22+
}
23+
}
24+
free(buffer);
25+
26+
return 0;
27+
}

0 commit comments

Comments
 (0)