Skip to content

Commit

Permalink
Merge pull request #48 from tino/more-automated-testing
Browse files Browse the repository at this point in the history
More automated testing
  • Loading branch information
Tino de Bruijn authored Oct 29, 2016
2 parents 85c67f2 + 5a27348 commit 7a9ef22
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 48 deletions.
14 changes: 12 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,18 @@ python:
- "3.4"
- "3.5"


# install deps
install: pip install -r requirements.txt
install:
- pip install flake8 isort coverage coveralls
- pip install -r requirements.txt

before_script:
- flake8 --show-source .
- isort -rc .

# run tests
script: python tests.py
script: coverage run --source=pyfirmata tests.py

after_success:
- coveralls
4 changes: 3 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ on Python 2.7, 3.3 and 3.4.

.. _Firmata: http://firmata.org

Test status:
Test & coverage status:

.. image:: https://travis-ci.org/tino/pyFirmata.png?branch=master
:target: https://travis-ci.org/tino/pyFirmata

.. image:: https://coveralls.io/repos/github/tino/pyFirmata/badge.svg?branch=master
:target: https://coveralls.io/github/tino/pyFirmata?branch=master

Installation
============
Expand Down
5 changes: 4 additions & 1 deletion pyfirmata/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from .pyfirmata import * # NOQA
from .boards import BOARDS
from .pyfirmata import * # NOQA

# TODO: should change above import to an explicit list, but people might rely on
# it, so do it in a backwards breaking release

__version__ = '1.0.3' # Use bumpversion!

Expand Down
3 changes: 2 additions & 1 deletion pyfirmata/mockup.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ def write(self, value):
if self.mode == pyfirmata.UNAVAILABLE:
raise IOError("Cannot read from pin {0}".format(self.pin_number))
if self.mode == pyfirmata.INPUT:
raise IOError("{0} pin {1} is not an output".format(self.port and "Digital" or "Analog", self.get_pin_number()))
raise IOError("{0} pin {1} is not an output"
.format(self.port and "Digital" or "Analog", self.get_pin_number()))
if not self.port:
raise AttributeError("AnalogPin instance has no attribute 'write'")
# if value != self.read():
Expand Down
19 changes: 12 additions & 7 deletions pyfirmata/pyfirmata.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import serial

from .util import to_two_bytes, two_byte_iter_to_str, pin_list_to_board_dict
from .util import pin_list_to_board_dict, to_two_bytes, two_byte_iter_to_str

# Message command bytes (0x80(128) to 0xFF(255)) - straight from Firmata.h
DIGITAL_MESSAGE = 0x90 # send data for a digital pin
Expand Down Expand Up @@ -169,7 +169,7 @@ def auto_setup(self):
"""
self.add_cmd_handler(CAPABILITY_RESPONSE, self._handle_report_capability_response)
self.send_sysex(CAPABILITY_QUERY, [])
self.pass_time(0.1) # Serial SYNC
self.pass_time(0.1) # Serial SYNC

while self.bytes_available():
self.iterate()
Expand Down Expand Up @@ -215,11 +215,15 @@ def get_pin(self, pin_def):
part = getattr(self, a_d)
pin_nr = int(bits[1])
if pin_nr >= len(part):
raise InvalidPinDefError('Invalid pin definition: {0} at position 3 on {1}'.format(pin_def, self.name))
raise InvalidPinDefError('Invalid pin definition: {0} at position 3 on {1}'
.format(pin_def, self.name))
if getattr(part[pin_nr], 'mode', None) == UNAVAILABLE:
raise InvalidPinDefError('Invalid pin definition: UNAVAILABLE pin {0} at position on {1}'.format(pin_def, self.name))
raise InvalidPinDefError('Invalid pin definition: '
'UNAVAILABLE pin {0} at position on {1}'
.format(pin_def, self.name))
if self.taken[a_d][pin_nr]:
raise PinAlreadyTakenError('{0} pin {1} is already taken on {2}'.format(a_d, bits[1], self.name))
raise PinAlreadyTakenError('{0} pin {1} is already taken on {2}'
.format(a_d, bits[1], self.name))
# ok, should be available
pin = part[pin_nr]
self.taken[a_d][pin_nr] = True
Expand Down Expand Up @@ -461,7 +465,7 @@ def _set_mode(self, mode):
if mode == SERVO:
if self.type != DIGITAL:
raise IOError("Only digital pins can drive servos! {0} is not"
"digital".format(self))
"digital".format(self))
self._mode = SERVO
self.board.servo_config(self.pin_number)
return
Expand Down Expand Up @@ -525,7 +529,8 @@ def write(self, value):
if self.mode is UNAVAILABLE:
raise IOError("{0} can not be used through Firmata".format(self))
if self.mode is INPUT:
raise IOError("{0} is set up as an INPUT and can therefore not be written to".format(self))
raise IOError("{0} is set up as an INPUT and can therefore not be written to"
.format(self))
if value is not self.value:
self.value = value
if self.mode is OUTPUT:
Expand Down
11 changes: 11 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,14 @@ parse = "__version__ = '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)'"
[wheel]
universal = true

[flake8]
max_line_length = 99
exclude = docs
ignore = W503,F405

[isort]
line_length = 99
multi_line_output = 5
balanced_wrapping = 1
skip = build,dist,docs
not_skip = __init__.py
75 changes: 39 additions & 36 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
import pyfirmata
from pyfirmata import mockup
from pyfirmata.boards import BOARDS
from pyfirmata.util import (break_to_bytes, from_two_bytes,
str_to_two_byte_iter, to_two_bytes,
two_byte_iter_to_str)
from pyfirmata.util import (
break_to_bytes, from_two_bytes, str_to_two_byte_iter, to_two_bytes, two_byte_iter_to_str
)


# Messages todo left:

Expand Down Expand Up @@ -135,41 +136,41 @@ def test_handle_capability_response(self):
'analog': (0, 1),
'pwm': (1, 2),
'servo': (0, 1, 2),
# 'i2c': (2), # TODO 2.3 specs
# 'i2c': (2), # TODO 2.3 specs
'disabled': (0,),
}

# Eg: (127)
unavailible_pin = [
0x7F, # END_SYSEX (Pin delimiter)
0x7F, # END_SYSEX (Pin delimiter)
]

# Eg: (0, 1, 1, 1, 3, 8, 4, 14, 127)
digital_pin = [
0x00, # INPUT
0x01,
0x01, # OUTPUT
0x01,
0x03, # PWM
0x08,
0x7F, # END_SYSEX (Pin delimiter)
0x00, # INPUT
0x01,
0x01, # OUTPUT
0x01,
0x03, # PWM
0x08,
0x7F, # END_SYSEX (Pin delimiter)
]

# Eg. (0, 1, 1, 1, 4, 14, 127)
analog_pin = [
0x00, # INPUT
0x01,
0x01, # OUTPUT
0x01,
0x02, # ANALOG
0x0A,
0x06, # I2C
0x01,
0x7F, # END_SYSEX (Pin delimiter)
0x00, # INPUT
0x01,
0x01, # OUTPUT
0x01,
0x02, # ANALOG
0x0A,
0x06, # I2C
0x01,
0x7F, # END_SYSEX (Pin delimiter)
]

data_arduino = list(
[0x6C] # CAPABILITY_RESPONSE
[0x6C] # CAPABILITY_RESPONSE
+ unavailible_pin
+ digital_pin * 2
+ analog_pin * 2
Expand Down Expand Up @@ -273,8 +274,7 @@ def test_send_sysex_too_big_data(self):
self.assertRaises(ValueError, self.board.send_sysex, 0x79, [256, 1])

def test_receive_sysex_message(self):
sysex = bytearray([0xF0, 0x79, 2, 1, ord('a'), 0, ord('b'),
0, ord('c'), 0, 0xF7])
sysex = bytearray([0xF0, 0x79, 2, 1, ord('a'), 0, ord('b'), 0, ord('c'), 0, 0xF7])
self.board.sp.write(sysex)
while len(self.board.sp):
self.board.iterate()
Expand Down Expand Up @@ -315,22 +315,24 @@ def test_too_much_data(self):
# 10 angle MSB
def test_servo_config(self):
self.board.servo_config(2)
data = chain([0xF0, 0x70, 2], to_two_bytes(544),
to_two_bytes(2400), [0xF7, 0xE0 + 2, 0, 0])
data = chain([0xF0, 0x70, 2],
to_two_bytes(544),
to_two_bytes(2400),
[0xF7, 0xE0 + 2, 0, 0])
self.assert_serial(*list(data))

def test_servo_config_min_max_pulse(self):
self.board.servo_config(2, 600, 2000)
data = chain([0xF0, 0x70, 2], to_two_bytes(600),
to_two_bytes(2000), [0xF7, 0xE0 + 2, 0, 0])
data = chain([0xF0, 0x70, 2],
to_two_bytes(600),
to_two_bytes(2000),
[0xF7, 0xE0 + 2, 0, 0])
self.assert_serial(*data)

def test_servo_config_min_max_pulse_angle(self):
self.board.servo_config(2, 600, 2000, angle=90)
data = chain([0xF0, 0x70, 2], to_two_bytes(600),
to_two_bytes(2000), [0xF7])
angle_set = [0xE0 + 2, 90 % 128,
90 >> 7] # Angle set happens through analog message
data = chain([0xF0, 0x70, 2], to_two_bytes(600), to_two_bytes(2000), [0xF7])
angle_set = [0xE0 + 2, 90 % 128, 90 >> 7] # Angle set happens through analog message
data = list(data) + angle_set
self.assert_serial(*data)

Expand All @@ -340,8 +342,10 @@ def test_servo_config_invalid_pin(self):
def test_set_mode_servo(self):
p = self.board.digital[2]
p.mode = pyfirmata.SERVO
data = chain([0xF0, 0x70, 2], to_two_bytes(544),
to_two_bytes(2400), [0xF7, 0xE0 + 2, 0, 0])
data = chain([0xF0, 0x70, 2],
to_two_bytes(544),
to_two_bytes(2400),
[0xF7, 0xE0 + 2, 0, 0])
self.assert_serial(*data)


Expand Down Expand Up @@ -431,8 +435,7 @@ def test_correct_digital_input_first_pin_issue_9(self):
pin = self.board.get_pin('d:8:i')
mask = 0
mask |= 1 << 0 # set pin 0 high
self.board._handle_digital_message(pin.port.port_number,
mask % 128, mask >> 7)
self.board._handle_digital_message(pin.port.port_number, mask % 128, mask >> 7)
self.assertEqual(pin.value, True)

def test_handle_digital_inputs(self):
Expand Down

0 comments on commit 7a9ef22

Please sign in to comment.