From 34bc900cb6d1e003b1898d408f324026fd2e0e56 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Sun, 25 Oct 2015 21:56:34 -0400 Subject: [PATCH 01/17] Add some bool property tests --- .../instruments/tests/test_util_fns.py | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/instruments/instruments/tests/test_util_fns.py b/instruments/instruments/tests/test_util_fns.py index 021d5588c..1021cbd4d 100644 --- a/instruments/instruments/tests/test_util_fns.py +++ b/instruments/instruments/tests/test_util_fns.py @@ -98,13 +98,18 @@ def test_assume_units_correct(): def test_assume_units_failures(): assume_units(1, 'm').rescale('s') -def test_bool_property(): +## Test Property Factories ## + +def test_bool_property_basics(): class BoolMock(MockInstrument): mock1 = bool_property('MOCK1', 'ON', 'OFF') mock2 = bool_property('MOCK2', 'YES', 'NO') mock = BoolMock({'MOCK1?': 'OFF', 'MOCK2?': 'YES'}) + assert hasattr(mock, 'mock1') + assert hasattr(mock, 'mock2') + assert not mock.mock1 assert mock.mock2 @@ -113,6 +118,36 @@ class BoolMock(MockInstrument): eq_(mock.value, 'MOCK1?\nMOCK2?\nMOCK1 ON\nMOCK2 NO\n') +def test_bool_property_set_fmt(): + class BoolMock(MockInstrument): + mock1 = bool_property('MOCK1', 'ON', 'OFF', set_fmt="{}={}") + + mock_instrument = BoolMock({'MOCK1?': 'OFF'}) + + mock_instrument.mock1 = True + + eq_(mock_instrument.value, 'MOCK1=ON') + +@raises(AttributeError) +def test_bool_property_read_only(): + class BoolMock(MockInstrument): + mock1 = bool_property('MOCK1', 'ON', 'OFF', readonly=True) + + mock_instrument = BoolMock({'MOCK1?': 'OFF'}) + + assert mock_instrument.mock1 = False # Can read + mock_instrument.mock1 = "Foo" # Should raise AttributeError + +@raises(AttributeError) +def test_bool_property_write_only(): + class BoolMock(MockInstrument): + mock1 = bool_property('MOCK1', 'ON', 'OFF', writeonly=True) + + mock_instrument = BoolMock({'MOCK1?': 'OFF'}) + + mock_instrument.mock1 = "OFF" # Can write + mock_instrument.mock1 # Should raise AttributeError + def test_enum_property(): class SillyEnum(Enum): a = 'aa' From 5046bf3e01377075e968ea449471907593bcc6e4 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Sun, 25 Oct 2015 21:58:04 -0400 Subject: [PATCH 02/17] Syntax error --- instruments/instruments/tests/test_util_fns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instruments/instruments/tests/test_util_fns.py b/instruments/instruments/tests/test_util_fns.py index 1021cbd4d..46858b5e6 100644 --- a/instruments/instruments/tests/test_util_fns.py +++ b/instruments/instruments/tests/test_util_fns.py @@ -135,7 +135,7 @@ class BoolMock(MockInstrument): mock_instrument = BoolMock({'MOCK1?': 'OFF'}) - assert mock_instrument.mock1 = False # Can read + assert mock_instrument.mock1 == False # Can read mock_instrument.mock1 = "Foo" # Should raise AttributeError @raises(AttributeError) From 12df77cea49cc7d00c8c308059f215b21e770f7a Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Sun, 25 Oct 2015 22:01:15 -0400 Subject: [PATCH 03/17] Removed extra getter calls --- instruments/instruments/tests/test_util_fns.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/instruments/instruments/tests/test_util_fns.py b/instruments/instruments/tests/test_util_fns.py index 46858b5e6..2c87e6574 100644 --- a/instruments/instruments/tests/test_util_fns.py +++ b/instruments/instruments/tests/test_util_fns.py @@ -107,9 +107,6 @@ class BoolMock(MockInstrument): mock = BoolMock({'MOCK1?': 'OFF', 'MOCK2?': 'YES'}) - assert hasattr(mock, 'mock1') - assert hasattr(mock, 'mock2') - assert not mock.mock1 assert mock.mock2 From 24464e09860de94af323db97bbb1df3ba2f34c30 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Sun, 25 Oct 2015 22:02:55 -0400 Subject: [PATCH 04/17] Don't forget your white space characters! --- instruments/instruments/tests/test_util_fns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instruments/instruments/tests/test_util_fns.py b/instruments/instruments/tests/test_util_fns.py index 2c87e6574..34044de13 100644 --- a/instruments/instruments/tests/test_util_fns.py +++ b/instruments/instruments/tests/test_util_fns.py @@ -123,7 +123,7 @@ class BoolMock(MockInstrument): mock_instrument.mock1 = True - eq_(mock_instrument.value, 'MOCK1=ON') + eq_(mock_instrument.value, 'MOCK1=ON\n') @raises(AttributeError) def test_bool_property_read_only(): From fe6e83a6bea5cf1b9ec10da4bac2bf8dff882a33 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Wed, 16 Dec 2015 21:11:21 -0500 Subject: [PATCH 05/17] Moved some tests into their own files --- .../tests/test_property_factories.py | 143 +++++++++++ .../instruments/tests/test_split_str.py | 157 ++++++++++++ .../instruments/tests/test_util_fns.py | 227 +----------------- 3 files changed, 301 insertions(+), 226 deletions(-) create mode 100644 instruments/instruments/tests/test_property_factories.py create mode 100644 instruments/instruments/tests/test_split_str.py diff --git a/instruments/instruments/tests/test_property_factories.py b/instruments/instruments/tests/test_property_factories.py new file mode 100644 index 000000000..fbfd042e7 --- /dev/null +++ b/instruments/instruments/tests/test_property_factories.py @@ -0,0 +1,143 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +## +# test_util_fns.py: Tests various utility functions. +## +# © 2013-2015 Steven Casagrande (scasagrande@galvant.ca). +# +# This file is a part of the InstrumentKit project. +# Licensed under the AGPL version 3. +## +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +## + +## IMPORTS #################################################################### + +import quantities as pq +from cStringIO import StringIO + +from nose.tools import raises, eq_ + +from instruments.util_fns import ( + ProxyList, + assume_units, bool_property, enum_property, int_property, + split_unit_str +) + +from flufl.enum import Enum + +## CLASSES #################################################################### + +class MockInstrument(object): + """ + Mock class that admits sendcmd/query but little else such that property + factories can be tested by deriving from the class. + """ + + def __init__(self, responses=None): + self._buf = StringIO() + self._responses = responses if responses is not None else {} + + @property + def value(self): + return self._buf.getvalue() + + def sendcmd(self, cmd): + self._buf.write("{}\n".format(cmd)) + + def query(self, cmd): + self.sendcmd(cmd) + return self._responses[cmd.strip()] + +## TEST CASES ################################################################# + +## Bool Property Factories ## + +def test_bool_property_basics(): + class BoolMock(MockInstrument): + mock1 = bool_property('MOCK1', 'ON', 'OFF') + mock2 = bool_property('MOCK2', 'YES', 'NO') + + mock = BoolMock({'MOCK1?': 'OFF', 'MOCK2?': 'YES'}) + + assert not mock.mock1 + assert mock.mock2 + + mock.mock1 = True + mock.mock2 = False + + eq_(mock.value, 'MOCK1?\nMOCK2?\nMOCK1 ON\nMOCK2 NO\n') + +def test_bool_property_set_fmt(): + class BoolMock(MockInstrument): + mock1 = bool_property('MOCK1', 'ON', 'OFF', set_fmt="{}={}") + + mock_instrument = BoolMock({'MOCK1?': 'OFF'}) + + mock_instrument.mock1 = True + + eq_(mock_instrument.value, 'MOCK1=ON\n') + +@raises(AttributeError) +def test_bool_property_read_only(): + class BoolMock(MockInstrument): + mock1 = bool_property('MOCK1', 'ON', 'OFF', readonly=True) + + mock_instrument = BoolMock({'MOCK1?': 'OFF'}) + + assert mock_instrument.mock1 == False # Can read + mock_instrument.mock1 = "Foo" # Should raise AttributeError + +@raises(AttributeError) +def test_bool_property_write_only(): + class BoolMock(MockInstrument): + mock1 = bool_property('MOCK1', 'ON', 'OFF', writeonly=True) + + mock_instrument = BoolMock({'MOCK1?': 'OFF'}) + + mock_instrument.mock1 = "OFF" # Can write + mock_instrument.mock1 # Should raise AttributeError + +## Enum Property Factories ## + +def test_enum_property(): + class SillyEnum(Enum): + a = 'aa' + b = 'bb' + + class EnumMock(MockInstrument): + a = enum_property('MOCK:A', SillyEnum) + b = enum_property('MOCK:B', SillyEnum) + + mock = EnumMock({'MOCK:A?': 'aa', 'MOCK:B?': 'bb'}) + + assert mock.a is SillyEnum.a + assert mock.b is SillyEnum.b + + # Test EnumValues, string values and string names. + mock.a = SillyEnum.b + mock.b = 'a' + mock.b = 'bb' + + eq_(mock.value, 'MOCK:A?\nMOCK:B?\nMOCK:A bb\nMOCK:B aa\nMOCK:B bb\n') + +## Int Property Factories ## + +@raises(ValueError) +def test_int_property_valid_set(): + class IntMock(MockInstrument): + mock = int_property('MOCK', valid_set=set([1, 2])) + + mock = IntMock() + mock.mock = 3 diff --git a/instruments/instruments/tests/test_split_str.py b/instruments/instruments/tests/test_split_str.py new file mode 100644 index 000000000..f393e3955 --- /dev/null +++ b/instruments/instruments/tests/test_split_str.py @@ -0,0 +1,157 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +## +# test_util_fns.py: Tests various utility functions. +## +# © 2013-2015 Steven Casagrande (scasagrande@galvant.ca). +# +# This file is a part of the InstrumentKit project. +# Licensed under the AGPL version 3. +## +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +## + +## IMPORTS #################################################################### + +import quantities as pq + +from nose.tools import raises, eq_ + +from instruments.util_fns import ( + split_unit_str +) + +## TEST CASES ################################################################# + +def test_split_unit_str_magnitude_and_units(): + """ + split_unit_str: Given the input "42 foobars" I expect the output + to be (42, "foobars"). + + This checks that "[val] [units]" works where val is a non-scientific number + """ + mag, units = split_unit_str("42 foobars") + eq_(mag, 42) + eq_(units, "foobars") + +def test_split_unit_str_magnitude_and_default_units(): + """ + split_unit_str: Given the input "42" and default_units="foobars" + I expect output to be (42, "foobars"). + + This checks that when given a string without units, the function returns + default_units as the units. + """ + mag, units = split_unit_str("42", default_units="foobars") + eq_(mag, 42) + eq_(units, "foobars") + +def test_split_unit_str_ignore_default_units(): + """ + split_unit_str: Given the input "42 snafus" and default_units="foobars" + I expect the output to be (42, "snafus"). + + This verifies that if the input has units, then any specified default_units + are ignored. + """ + mag, units = split_unit_str("42 snafus", default_units="foobars") + eq_(mag, 42) + eq_(units, "snafus") + +def test_split_unit_str_lookups(): + """ + split_unit_str: Given the input "42 FOO" and a dictionary for our units + lookup, I expect the output to be (42, "foobars"). + + This checks that the unit lookup parameter is correctly called, which can be + used to map between units as string and their pyquantities equivalent. + """ + unit_dict = { + "FOO": "foobars", + "SNA": "snafus" + } + mag, units = split_unit_str("42 FOO", lookup=unit_dict.__getitem__) + eq_(mag, 42) + eq_(units, "foobars") + +def test_split_unit_str_scientific_notation(): + """ + split_unit_str: Given inputs of scientific notation, I expect the output + to correctly represent the inputted magnitude. + + This checks that inputs with scientific notation are correctly converted + to floats. + """ + # No signs, no units + mag, units = split_unit_str("123E1") + eq_(mag, 1230) + eq_(units, pq.dimensionless) + # Negative exponential, no units + mag, units = split_unit_str("123E-1") + eq_(mag, 12.3) + eq_(units, pq.dimensionless) + # Negative magnitude, no units + mag, units = split_unit_str("-123E1") + eq_(mag, -1230) + eq_(units, pq.dimensionless) + # No signs, with units + mag, units = split_unit_str("123E1 foobars") + eq_(mag, 1230) + eq_(units, "foobars") + # Signs everywhere, with units + mag, units = split_unit_str("-123E-1 foobars") + eq_(mag, -12.3) + eq_(units, "foobars") + # Lower case e + mag, units = split_unit_str("123e1") + eq_(mag, 1230) + eq_(units, pq.dimensionless) + +@raises(ValueError) +def test_split_unit_str_empty_string(): + """ + split_unit_str: Given an empty string, I expect the function to raise + a ValueError. + """ + mag, units = split_unit_str("") + +@raises(ValueError) +def test_split_unit_str_only_exponential(): + """ + split_unit_str: Given a string with only an exponential, I expect the + function to raise a ValueError. + """ + mag, units = split_unit_str("E3") + +def test_split_unit_str_magnitude_with_decimal(): + """ + split_unit_str: Given a string with magnitude containing a decimal, I + expect the function to correctly parse the magnitude. + """ + # Decimal and units + mag, units = split_unit_str("123.4 foobars") + eq_(mag, 123.4) + eq_(units, "foobars") + # Decimal, units, and exponential + mag, units = split_unit_str("123.4E1 foobars") + eq_(mag, 1234) + eq_(units, "foobars") + +@raises(ValueError) +def test_split_unit_str_only_units(): + """ + split_unit_str: Given a bad string containing only units (ie, no numbers), + I expect the function to raise a ValueError. + """ + mag, units = split_unit_str("foobars") diff --git a/instruments/instruments/tests/test_util_fns.py b/instruments/instruments/tests/test_util_fns.py index 34044de13..af862db1d 100644 --- a/instruments/instruments/tests/test_util_fns.py +++ b/instruments/instruments/tests/test_util_fns.py @@ -31,35 +31,11 @@ from instruments.util_fns import ( ProxyList, - assume_units, bool_property, enum_property, int_property, - split_unit_str + assume_units ) from flufl.enum import Enum -## CLASSES #################################################################### - -class MockInstrument(object): - """ - Mock class that admits sendcmd/query but little else such that property - factories can be tested by deriving from the class. - """ - - def __init__(self, responses=None): - self._buf = StringIO() - self._responses = responses if responses is not None else {} - - @property - def value(self): - return self._buf.getvalue() - - def sendcmd(self, cmd): - self._buf.write("{}\n".format(cmd)) - - def query(self, cmd): - self.sendcmd(cmd) - return self._responses[cmd.strip()] - ## TEST CASES ################################################################# def test_ProxyList(): @@ -97,204 +73,3 @@ def test_assume_units_correct(): @raises(ValueError) def test_assume_units_failures(): assume_units(1, 'm').rescale('s') - -## Test Property Factories ## - -def test_bool_property_basics(): - class BoolMock(MockInstrument): - mock1 = bool_property('MOCK1', 'ON', 'OFF') - mock2 = bool_property('MOCK2', 'YES', 'NO') - - mock = BoolMock({'MOCK1?': 'OFF', 'MOCK2?': 'YES'}) - - assert not mock.mock1 - assert mock.mock2 - - mock.mock1 = True - mock.mock2 = False - - eq_(mock.value, 'MOCK1?\nMOCK2?\nMOCK1 ON\nMOCK2 NO\n') - -def test_bool_property_set_fmt(): - class BoolMock(MockInstrument): - mock1 = bool_property('MOCK1', 'ON', 'OFF', set_fmt="{}={}") - - mock_instrument = BoolMock({'MOCK1?': 'OFF'}) - - mock_instrument.mock1 = True - - eq_(mock_instrument.value, 'MOCK1=ON\n') - -@raises(AttributeError) -def test_bool_property_read_only(): - class BoolMock(MockInstrument): - mock1 = bool_property('MOCK1', 'ON', 'OFF', readonly=True) - - mock_instrument = BoolMock({'MOCK1?': 'OFF'}) - - assert mock_instrument.mock1 == False # Can read - mock_instrument.mock1 = "Foo" # Should raise AttributeError - -@raises(AttributeError) -def test_bool_property_write_only(): - class BoolMock(MockInstrument): - mock1 = bool_property('MOCK1', 'ON', 'OFF', writeonly=True) - - mock_instrument = BoolMock({'MOCK1?': 'OFF'}) - - mock_instrument.mock1 = "OFF" # Can write - mock_instrument.mock1 # Should raise AttributeError - -def test_enum_property(): - class SillyEnum(Enum): - a = 'aa' - b = 'bb' - - class EnumMock(MockInstrument): - a = enum_property('MOCK:A', SillyEnum) - b = enum_property('MOCK:B', SillyEnum) - - mock = EnumMock({'MOCK:A?': 'aa', 'MOCK:B?': 'bb'}) - - assert mock.a is SillyEnum.a - assert mock.b is SillyEnum.b - - # Test EnumValues, string values and string names. - mock.a = SillyEnum.b - mock.b = 'a' - mock.b = 'bb' - - eq_(mock.value, 'MOCK:A?\nMOCK:B?\nMOCK:A bb\nMOCK:B aa\nMOCK:B bb\n') - -# TODO: test other property factories! - -@raises(ValueError) -def test_int_property_valid_set(): - class IntMock(MockInstrument): - mock = int_property('MOCK', valid_set=set([1, 2])) - - mock = IntMock() - mock.mock = 3 - -def test_split_unit_str_magnitude_and_units(): - """ - split_unit_str: Given the input "42 foobars" I expect the output - to be (42, "foobars"). - - This checks that "[val] [units]" works where val is a non-scientific number - """ - mag, units = split_unit_str("42 foobars") - eq_(mag, 42) - eq_(units, "foobars") - -def test_split_unit_str_magnitude_and_default_units(): - """ - split_unit_str: Given the input "42" and default_units="foobars" - I expect output to be (42, "foobars"). - - This checks that when given a string without units, the function returns - default_units as the units. - """ - mag, units = split_unit_str("42", default_units="foobars") - eq_(mag, 42) - eq_(units, "foobars") - -def test_split_unit_str_ignore_default_units(): - """ - split_unit_str: Given the input "42 snafus" and default_units="foobars" - I expect the output to be (42, "snafus"). - - This verifies that if the input has units, then any specified default_units - are ignored. - """ - mag, units = split_unit_str("42 snafus", default_units="foobars") - eq_(mag, 42) - eq_(units, "snafus") - -def test_split_unit_str_lookups(): - """ - split_unit_str: Given the input "42 FOO" and a dictionary for our units - lookup, I expect the output to be (42, "foobars"). - - This checks that the unit lookup parameter is correctly called, which can be - used to map between units as string and their pyquantities equivalent. - """ - unit_dict = { - "FOO": "foobars", - "SNA": "snafus" - } - mag, units = split_unit_str("42 FOO", lookup=unit_dict.__getitem__) - eq_(mag, 42) - eq_(units, "foobars") - -def test_split_unit_str_scientific_notation(): - """ - split_unit_str: Given inputs of scientific notation, I expect the output - to correctly represent the inputted magnitude. - - This checks that inputs with scientific notation are correctly converted - to floats. - """ - # No signs, no units - mag, units = split_unit_str("123E1") - eq_(mag, 1230) - eq_(units, pq.dimensionless) - # Negative exponential, no units - mag, units = split_unit_str("123E-1") - eq_(mag, 12.3) - eq_(units, pq.dimensionless) - # Negative magnitude, no units - mag, units = split_unit_str("-123E1") - eq_(mag, -1230) - eq_(units, pq.dimensionless) - # No signs, with units - mag, units = split_unit_str("123E1 foobars") - eq_(mag, 1230) - eq_(units, "foobars") - # Signs everywhere, with units - mag, units = split_unit_str("-123E-1 foobars") - eq_(mag, -12.3) - eq_(units, "foobars") - # Lower case e - mag, units = split_unit_str("123e1") - eq_(mag, 1230) - eq_(units, pq.dimensionless) - -@raises(ValueError) -def test_split_unit_str_empty_string(): - """ - split_unit_str: Given an empty string, I expect the function to raise - a ValueError. - """ - mag, units = split_unit_str("") - -@raises(ValueError) -def test_split_unit_str_only_exponential(): - """ - split_unit_str: Given a string with only an exponential, I expect the - function to raise a ValueError. - """ - mag, units = split_unit_str("E3") - -def test_split_unit_str_magnitude_with_decimal(): - """ - split_unit_str: Given a string with magnitude containing a decimal, I - expect the function to correctly parse the magnitude. - """ - # Decimal and units - mag, units = split_unit_str("123.4 foobars") - eq_(mag, 123.4) - eq_(units, "foobars") - # Decimal, units, and exponential - mag, units = split_unit_str("123.4E1 foobars") - eq_(mag, 1234) - eq_(units, "foobars") - -@raises(ValueError) -def test_split_unit_str_only_units(): - """ - split_unit_str: Given a bad string containing only units (ie, no numbers), - I expect the function to raise a ValueError. - """ - mag, units = split_unit_str("foobars") - From 1eafa73067eee99575aea3329edffd3ae840bf0f Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Thu, 17 Dec 2015 17:51:33 -0500 Subject: [PATCH 06/17] More property factory tests --- .../tests/test_property_factories.py | 95 ++++++++++++++++++- 1 file changed, 91 insertions(+), 4 deletions(-) diff --git a/instruments/instruments/tests/test_property_factories.py b/instruments/instruments/tests/test_property_factories.py index fbfd042e7..a11288085 100644 --- a/instruments/instruments/tests/test_property_factories.py +++ b/instruments/instruments/tests/test_property_factories.py @@ -30,9 +30,8 @@ from nose.tools import raises, eq_ from instruments.util_fns import ( - ProxyList, - assume_units, bool_property, enum_property, int_property, - split_unit_str + ProxyList, assume_units, + rproperty, bool_property, enum_property, int_property ) from flufl.enum import Enum @@ -62,6 +61,56 @@ def query(self, cmd): ## TEST CASES ################################################################# +## rproperty ## + +def test_rproperty_basic(): + class Mock(MockInstrument): + def __init__(self): + self._value = 0 + def mockget(self): + return self._value + def mockset(self, newval): + self._value = newval + mockproperty = rproperty(fget=mockget, fset=mockset) + + mock_inst = Mock() + mock_inst.mockproperty = 1 + eq_(mock_inst.mockproperty, 1) + +@raises(AttributeError) +def test_rproperty_readonly(): + class Mock(MockInstrument): + def __init__(self): + self._value = 0 + def mockget(self): + return self._value + def mockset(self, newval): + self._value = newval + mockproperty = rproperty(fget=mockget, fset=mockset, readonly=True) + + mock_inst = Mock() + eq_(mock_inst.mockproperty, 0) + mock_inst.mockproperty = 1 # Should raise attr error + +@raises(AttributeError) +def test_rproperty_writeonly(): + class Mock(MockInstrument): + def __init__(self): + self._value = 0 + def mockget(self): + return self._value + def mockset(self, newval): + self._value = newval + mockproperty = rproperty(fget=mockget, fset=mockset, readonly=True) + + mock_inst = Mock() + eq_(mock_inst.mockproperty, 0) # Should raise attr error + mock_inst.mockproperty = 1 + +@raises(ValueError) +def test_rproperty_readonly_and_writeonly(): + mockproperty = rproperty(readonly=True, writeonly=True) + ## Bool Property Factories ## def test_bool_property_basics(): @@ -131,13 +180,51 @@ class EnumMock(MockInstrument): mock.b = 'bb' eq_(mock.value, 'MOCK:A?\nMOCK:B?\nMOCK:A bb\nMOCK:B aa\nMOCK:B bb\n') + +def test_enum_property_set_fmt(): + class SillyEnum(Enum): + a = 'aa' + + class EnumMock(MockInstrument): + a = enum_property('MOCK:A', SillyEnum, set_fmt="{}={}") + + mock_instrument = EnumMock() + + mock_instrument.a = 'aa' + + eq_(mock_instrument.value, 'MOCK:A=aa\n') + +def test_enum_property_input_decoration(): + class SillyEnum(Enum): + a = 'aa' + + class EnumMock(MockInstrument): + def input_decorator(input): + return 'aa' + a = enum_property('MOCK:A', SillyEnum, input_decoration=input_decorator) + + mock_instrument = EnumMock({'MOCK:A?': 'garbage'}) + + assert mock_instrument.a is SillyEnum.a ## Int Property Factories ## @raises(ValueError) -def test_int_property_valid_set(): +def test_int_property_invalid_set(): class IntMock(MockInstrument): mock = int_property('MOCK', valid_set=set([1, 2])) mock = IntMock() mock.mock = 3 + +def test_int_property_valid_set(): + class IntMock(MockInstrument): + int_property = int_property('MOCK', valid_set=set([1, 2])) + + mock_inst = IntMock({'MOCK?': '1'}) + + assert mock_inst.int_property is 1 + + mock_inst.int_property = 2 + + eq_(mock_inst.value, 'MOCK?\nMOCK 2\n') From c07473b81b3e46b1bb3ad184c87523d18ca4d920 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Fri, 18 Dec 2015 08:56:52 -0500 Subject: [PATCH 07/17] More proxylist tests --- .../instruments/tests/test_util_fns.py | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/instruments/instruments/tests/test_util_fns.py b/instruments/instruments/tests/test_util_fns.py index af862db1d..6a3f60eea 100644 --- a/instruments/instruments/tests/test_util_fns.py +++ b/instruments/instruments/tests/test_util_fns.py @@ -38,16 +38,12 @@ ## TEST CASES ################################################################# -def test_ProxyList(): +def test_ProxyList_basics(): class ProxyChild(object): def __init__(self, parent, name): self._parent = parent self._name = name - class MockEnum(Enum): - a = "aa" - b = "bb" - parent = object() proxy_list = ProxyList(parent, ProxyChild, xrange(10)) @@ -56,10 +52,49 @@ class MockEnum(Enum): assert child._parent is parent assert child._name == 0 +def test_ProxyList_valid_range_is_enum(): + class ProxyChild(object): + def __init__(self, parent, name): + self._parent = parent + self._name = name + + class MockEnum(Enum): + a = "aa" + b = "bb" + + parent = object() + proxy_list = ProxyList(parent, ProxyChild, MockEnum) assert proxy_list['aa']._name == MockEnum.a assert proxy_list['b']._name == MockEnum.b assert proxy_list[MockEnum.a]._name == MockEnum.a + +def test_ProxyList_length(): + class ProxyChild(object): + def __init__(self, parent, name): + self._parent = parent + self._name = name + + parent = object() + + proxy_list = ProxyList(parent, ProxyChild, xrange(10)) + + eq_(len(proxy_list), 10) + +def test_ProxyList_iterator(): + class ProxyChild(object): + def __init__(self, parent, name): + self._parent = parent + self._name = name + + parent = object() + + proxy_list = ProxyList(parent, ProxyChild, xrange(10)) + + i = 0 + for item in proxy_list: + eq_(item._name, i) + i = i + 1 def test_assume_units_correct(): m = pq.Quantity(1, 'm') From 2474947f21a9c80a55e3547b23588f35480cd6e2 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Tue, 22 Dec 2015 20:59:00 -0500 Subject: [PATCH 08/17] Add invalid idx tests for proxylist --- .../instruments/tests/test_util_fns.py | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/instruments/instruments/tests/test_util_fns.py b/instruments/instruments/tests/test_util_fns.py index 6a3f60eea..d3053fdea 100644 --- a/instruments/instruments/tests/test_util_fns.py +++ b/instruments/instruments/tests/test_util_fns.py @@ -96,6 +96,36 @@ def __init__(self, parent, name): eq_(item._name, i) i = i + 1 +@raises(IndexError) +def test_ProxyList_invalid_idx_enum(): + class ProxyChild(object): + def __init__(self, parent, name): + self._parent = parent + self._name = name + + class MockEnum(Enum): + a = "aa" + b = "bb" + + parent = object() + + proxy_list = ProxyList(parent, ProxyChild, MockEnum) + + proxy_list['c'] # Should raise IndexError + +@raises(IndexError) +def test_ProxyList_invalid_idx(): + class ProxyChild(object): + def __init__(self, parent, name): + self._parent = parent + self._name = name + + parent = object() + + proxy_list = ProxyList(parent, ProxyChild, xrange(5)) + + proxy_list[10] # Should raise IndexError + def test_assume_units_correct(): m = pq.Quantity(1, 'm') From f1fcd0cab1d92dcc4856dcb30e0bcfe1938c795f Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Tue, 22 Dec 2015 22:25:48 -0500 Subject: [PATCH 09/17] More property factory tests --- .../tests/test_property_factories.py | 70 +++++++++++++++++-- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/instruments/instruments/tests/test_property_factories.py b/instruments/instruments/tests/test_property_factories.py index a11288085..47cdf3a18 100644 --- a/instruments/instruments/tests/test_property_factories.py +++ b/instruments/instruments/tests/test_property_factories.py @@ -31,7 +31,7 @@ from instruments.util_fns import ( ProxyList, assume_units, - rproperty, bool_property, enum_property, int_property + rproperty, bool_property, enum_property, int_property, string_property ) from flufl.enum import Enum @@ -89,8 +89,8 @@ def mockset(self, newval): mockproperty = rproperty(fget=mockget, fset=mockset, readonly=True) mock_inst = Mock() - eq_(mock_inst.mockproperty, 0) - mock_inst.mockproperty = 1 # Should raise attr error + eq_(mock_inst.mockproperty, 0) # Reading should pass + mock_inst.mockproperty = 1 # Writing should raise attr error @raises(AttributeError) def test_rproperty_writeonly(): @@ -104,8 +104,8 @@ def mockset(self, newval): mockproperty = rproperty(fget=mockget, fset=mockset, readonly=True) mock_inst = Mock() + mock_inst.mockproperty = 1 eq_(mock_inst.mockproperty, 0) # Should raise attr error - mock_inst.mockproperty = 1 @raises(ValueError) def test_rproperty_readonly_and_writeonly(): @@ -206,11 +206,26 @@ def input_decorator(input): mock_instrument = EnumMock({'MOCK:A?': 'garbage'}) assert mock_instrument.a is SillyEnum.a + +def test_enum_property_output_decoration(): + class SillyEnum(Enum): + a = 'aa' + + class EnumMock(MockInstrument): + def output_decorator(input): + return 'foobar' + a = enum_property('MOCK:A', SillyEnum, output_decoration=output_decorator) + + mock_instrument = EnumMock() + + mock_instrument.a = SillyEnum.a + + eq_(mock_instrument.value, 'MOCK:A foobar\n') ## Int Property Factories ## @raises(ValueError) -def test_int_property_invalid_set(): +def test_int_property_outside_valid_set(): class IntMock(MockInstrument): mock = int_property('MOCK', valid_set=set([1, 2])) @@ -228,3 +243,48 @@ class IntMock(MockInstrument): mock_inst.int_property = 2 eq_(mock_inst.value, 'MOCK?\nMOCK 2\n') + +def test_int_property_no_set(): + class IntMock(MockInstrument): + int_property = int_property('MOCK') + + mock_inst = IntMock() + + mock_inst.int_property = 1 + + eq_(mock_inst.value, 'MOCK 1\n') + +## String Property ## + +def test_string_property_basics(): + class StringMock(MockInstrument): + string_property = string_property('MOCK') + + mock_inst = StringMock({'MOCK?': '"foobar"'}) + + eq_(mock_inst.string_property, 'foobar') + + mock_inst.string_property = 'foo' + eq_(mock_inst.value, 'MOCK?\nMOCK "foo"\n') + +def test_string_property_different_bookmark_symbol(): + class StringMock(MockInstrument): + string_property = string_property('MOCK', bookmark_symbol='%^') + + mock_inst = StringMock({'MOCK?': '%^foobar%^'}) + + eq_(mock_inst.string_property, 'foobar') + + mock_inst.string_property = 'foo' + eq_(mock_inst.value, 'MOCK?\nMOCK %^foo%^\n') + +def test_string_property_no_bookmark_symbol(): + class StringMock(MockInstrument): + string_property = string_property('MOCK', bookmark_symbol='') + + mock_inst = StringMock({'MOCK?': 'foobar'}) + + eq_(mock_inst.string_property, 'foobar') + + mock_inst.string_property = 'foo' + eq_(mock_inst.value, 'MOCK?\nMOCK foo\n') From 144d137d7ab5085c34de9feab8110239b9aab042 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Wed, 23 Dec 2015 21:16:31 -0500 Subject: [PATCH 10/17] Unitless, unitful, and more enum property factory tests --- .../tests/test_property_factories.py | 171 +++++++++++++++++- 1 file changed, 170 insertions(+), 1 deletion(-) diff --git a/instruments/instruments/tests/test_property_factories.py b/instruments/instruments/tests/test_property_factories.py index 47cdf3a18..c808d51ce 100644 --- a/instruments/instruments/tests/test_property_factories.py +++ b/instruments/instruments/tests/test_property_factories.py @@ -31,7 +31,8 @@ from instruments.util_fns import ( ProxyList, assume_units, - rproperty, bool_property, enum_property, int_property, string_property + rproperty, bool_property, enum_property, int_property, string_property, + unitful_property, unitless_property ) from flufl.enum import Enum @@ -222,6 +223,97 @@ def output_decorator(input): eq_(mock_instrument.value, 'MOCK:A foobar\n') +@raises(AttributeError) +def test_enum_property_write_only(): + class SillyEnum(Enum): + a = 'aa' + + class EnumMock(MockInstrument): + a = enum_property('MOCK:A', SillyEnum, writeonly=True) + + mock_instrument = EnumMock() + + # Writing should pass + mock_instrument.a = SillyEnum.a + eq_(mock_instrument.value, 'MOCK:A aa\n') + + # Reading should fail + mock_instrument.a + +@raises(AttributeError) +def test_enum_property_read_only(): + class SillyEnum(Enum): + a = 'aa' + + class EnumMock(MockInstrument): + a = enum_property('MOCK:A', SillyEnum, readonly=True) + + mock_instrument = EnumMock({'MOCK:A?':'aa'}) + + # Reading should pass + eq_(mock_instrument.a, SillyEnum.a) + + # Writing should fail + mock_instrument.a = SillyEnum.a + +## Unitless Property ## + +def test_unitless_property_basics(): + class UnitlessMock(MockInstrument): + unitless_property = unitless_property('MOCK') + + mock_inst = UnitlessMock({'MOCK?':'1'}) + + eq_(mock_inst.unitless_property, 1) + + mock_inst.unitless_property = 1 + eq_(mock_inst.value, 'MOCK?\nMOCK {:e}\n'.format(1)) + +@raises(ValueError) +def test_unitless_property_units(): + class UnitlessMock(MockInstrument): + unitless_property = unitless_property('MOCK') + + mock_inst = UnitlessMock({'MOCK?':'1'}) + + mock_inst.unitless_property = 1 * pq.volt + +def test_unitless_property_format_code(): + class UnitlessMock(MockInstrument): + unitless_property = unitless_property('MOCK', format_code='{:f}') + + mock_inst = UnitlessMock() + + mock_inst.unitless_property = 1 + eq_(mock_inst.value, 'MOCK {:f}\n'.format(1)) + +@raises(AttributeError) +def test_unitless_property_write_only(): + class UnitlessMock(MockInstrument): + unitless_property = unitless_property('MOCK', writeonly=True) + + mock_inst = UnitlessMock() + + # Writing should pass + mock_inst.unitless_property = 1 + eq_(mock_inst.value, 'MOCK {:e}\n'.format(1)) + + # Reading should fail + mock_inst.unitless_property + +@raises(AttributeError) +def test_unitless_property_read_only(): + class UnitlessMock(MockInstrument): + unitless_property = unitless_property('MOCK', readonly=True) + + mock_inst = UnitlessMock({'MOCK?':'1'}) + + # Reading should pass + eq_(mock_inst.unitless_property, 1) + + # Writing should fail + mock_inst.unitless_property = 1 + ## Int Property Factories ## @raises(ValueError) @@ -254,6 +346,83 @@ class IntMock(MockInstrument): eq_(mock_inst.value, 'MOCK 1\n') +## Unitful Property ## + +def test_unitful_property_basics(): + class UnitfulMock(MockInstrument): + unitful_property = unitful_property('MOCK', units=pq.hertz) + + mock_inst = UnitfulMock({'MOCK?':'1000'}) + + eq_(mock_inst.unitful_property, 1000 * pq.hertz) + + mock_inst.unitful_property = 1000 * pq.hertz + eq_(mock_inst.value, 'MOCK?\nMOCK {:e}\n'.format(1000)) + +def test_unitful_property_format_code(): + class UnitfulMock(MockInstrument): + unitful_property = unitful_property('MOCK', pq.hertz, format_code='{:f}') + + mock_inst = UnitfulMock() + + mock_inst.unitful_property = 1000 * pq.hertz + eq_(mock_inst.value, 'MOCK {:f}\n'.format(1000)) + +def test_unitful_property_rescale_units(): + class UnitfulMock(MockInstrument): + unitful_property = unitful_property('MOCK', pq.hertz) + + mock_inst = UnitfulMock() + + mock_inst.unitful_property = 1 * pq.kilohertz + eq_(mock_inst.value, 'MOCK {:e}\n'.format(1000)) + +def test_unitful_property_no_units_on_set(): + class UnitfulMock(MockInstrument): + unitful_property = unitful_property('MOCK', pq.hertz) + + mock_inst = UnitfulMock() + + mock_inst.unitful_property = 1000 + eq_(mock_inst.value, 'MOCK {:e}\n'.format(1000)) + +@raises(ValueError) +def test_unitful_property_wrong_units(): + class UnitfulMock(MockInstrument): + unitful_property = unitful_property('MOCK', pq.hertz) + + mock_inst = UnitfulMock() + + mock_inst.unitful_property = 1 * pq.volt + +@raises(AttributeError) +def test_unitful_property_write_only(): + class UnitfulMock(MockInstrument): + unitful_property = unitful_property('MOCK', pq.hertz, writeonly=True) + + mock_inst = UnitfulMock() + + # Writing should pass + mock_inst.unitful_property = 1 * pq.hertz + eq_(mock_inst.value, 'MOCK {:e}\n'.format(1)) + + # Reading should fail + mock_inst.unitful_property + +@raises(AttributeError) +def test_unitful_property_read_only(): + class UnitfulMock(MockInstrument): + unitful_property = unitful_property('MOCK', pq.hertz, readonly=True) + + mock_inst = UnitfulMock({'MOCK?':'1'}) + + # Reading should pass + eq_(mock_inst.unitful_property, 1 * pq.hertz) + + # Writing should fail + mock_inst.unitful_property = 1 * pq.hertz + + ## String Property ## def test_string_property_basics(): From 2113ba53156836289461ac7d548cb34205c5d62b Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Wed, 23 Dec 2015 23:39:25 -0500 Subject: [PATCH 11/17] No coverage no logging --- instruments/instruments/util_fns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instruments/instruments/util_fns.py b/instruments/instruments/util_fns.py index 347052cd4..a46362d3b 100644 --- a/instruments/instruments/util_fns.py +++ b/instruments/instruments/util_fns.py @@ -327,7 +327,7 @@ def __getitem__(self, idx): def __len__(self): return len(self._valid_set) -if sys.version_info[0] == 2 and sys.version_info[1] == 6: +if sys.version_info[0] == 2 and sys.version_info[1] == 6: # pragma: no cover import logging From ba2ec1f05456b7cfc038f12d50d40f652499c171 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Thu, 24 Dec 2015 17:05:12 -0500 Subject: [PATCH 12/17] Replace asserts with nose.tools.eq_ --- .../tests/test_property_factories.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/instruments/instruments/tests/test_property_factories.py b/instruments/instruments/tests/test_property_factories.py index c808d51ce..8f0ccefb5 100644 --- a/instruments/instruments/tests/test_property_factories.py +++ b/instruments/instruments/tests/test_property_factories.py @@ -121,8 +121,8 @@ class BoolMock(MockInstrument): mock = BoolMock({'MOCK1?': 'OFF', 'MOCK2?': 'YES'}) - assert not mock.mock1 - assert mock.mock2 + eq_(mock.mock1, False) + eq_(mock.mock2, True) mock.mock1 = True mock.mock2 = False @@ -146,7 +146,7 @@ class BoolMock(MockInstrument): mock_instrument = BoolMock({'MOCK1?': 'OFF'}) - assert mock_instrument.mock1 == False # Can read + eq_(mock_instrument.mock1, False) # Can read mock_instrument.mock1 = "Foo" # Should raise AttributeError @raises(AttributeError) @@ -172,8 +172,8 @@ class EnumMock(MockInstrument): mock = EnumMock({'MOCK:A?': 'aa', 'MOCK:B?': 'bb'}) - assert mock.a is SillyEnum.a - assert mock.b is SillyEnum.b + eq_(mock.a, SillyEnum.a) + eq_(mock.b, SillyEnum.b) # Test EnumValues, string values and string names. mock.a = SillyEnum.b @@ -192,7 +192,6 @@ class EnumMock(MockInstrument): mock_instrument = EnumMock() mock_instrument.a = 'aa' - eq_(mock_instrument.value, 'MOCK:A=aa\n') def test_enum_property_input_decoration(): @@ -206,7 +205,7 @@ def input_decorator(input): mock_instrument = EnumMock({'MOCK:A?': 'garbage'}) - assert mock_instrument.a is SillyEnum.a + eq_(mock_instrument.a, SillyEnum.a) def test_enum_property_output_decoration(): class SillyEnum(Enum): @@ -330,10 +329,9 @@ class IntMock(MockInstrument): mock_inst = IntMock({'MOCK?': '1'}) - assert mock_inst.int_property is 1 - - mock_inst.int_property = 2 + eq_(mock_inst.int_property, 1) + mock_inst.int_property = 2 eq_(mock_inst.value, 'MOCK?\nMOCK 2\n') def test_int_property_no_set(): From 3f9d992d01e1afd8af9fa978cacdcf0bb6df7125 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Thu, 24 Dec 2015 23:42:57 -0500 Subject: [PATCH 13/17] Split read/writeonly tests into two: one for pass & fail each --- .../tests/test_property_factories.py | 159 ++++++++++++++---- 1 file changed, 127 insertions(+), 32 deletions(-) diff --git a/instruments/instruments/tests/test_property_factories.py b/instruments/instruments/tests/test_property_factories.py index 8f0ccefb5..b883fe4f6 100644 --- a/instruments/instruments/tests/test_property_factories.py +++ b/instruments/instruments/tests/test_property_factories.py @@ -140,24 +140,38 @@ class BoolMock(MockInstrument): eq_(mock_instrument.value, 'MOCK1=ON\n') @raises(AttributeError) -def test_bool_property_read_only(): +def test_bool_property_readonly_writing_fails(): class BoolMock(MockInstrument): mock1 = bool_property('MOCK1', 'ON', 'OFF', readonly=True) mock_instrument = BoolMock({'MOCK1?': 'OFF'}) - eq_(mock_instrument.mock1, False) # Can read - mock_instrument.mock1 = "Foo" # Should raise AttributeError + mock_instrument.mock1 = True + +def test_bool_property_readonly_reading_passes(): + class BoolMock(MockInstrument): + mock1 = bool_property('MOCK1', 'ON', 'OFF', readonly=True) + + mock_instrument = BoolMock({'MOCK1?': 'OFF'}) + + eq_(mock_instrument.mock1, False) @raises(AttributeError) -def test_bool_property_write_only(): +def test_bool_property_writeonly_reading_fails(): class BoolMock(MockInstrument): mock1 = bool_property('MOCK1', 'ON', 'OFF', writeonly=True) mock_instrument = BoolMock({'MOCK1?': 'OFF'}) - mock_instrument.mock1 = "OFF" # Can write - mock_instrument.mock1 # Should raise AttributeError + mock_instrument.mock1 + +def test_bool_property_writeonly_writing_passes(): + class BoolMock(MockInstrument): + mock1 = bool_property('MOCK1', 'ON', 'OFF', writeonly=True) + + mock_instrument = BoolMock({'MOCK1?': 'OFF'}) + + mock_instrument.mock1 = "OFF" ## Enum Property Factories ## @@ -181,7 +195,7 @@ class EnumMock(MockInstrument): mock.b = 'bb' eq_(mock.value, 'MOCK:A?\nMOCK:B?\nMOCK:A bb\nMOCK:B aa\nMOCK:B bb\n') - + def test_enum_property_set_fmt(): class SillyEnum(Enum): a = 'aa' @@ -223,7 +237,19 @@ def output_decorator(input): eq_(mock_instrument.value, 'MOCK:A foobar\n') @raises(AttributeError) -def test_enum_property_write_only(): +def test_enum_property_writeonly_reading_fails(): + class SillyEnum(Enum): + a = 'aa' + + class EnumMock(MockInstrument): + a = enum_property('MOCK:A', SillyEnum, writeonly=True) + + mock_instrument = EnumMock() + + # Reading should fail + mock_instrument.a + +def test_enum_property_writeonly_writing_passes(): class SillyEnum(Enum): a = 'aa' @@ -236,11 +262,8 @@ class EnumMock(MockInstrument): mock_instrument.a = SillyEnum.a eq_(mock_instrument.value, 'MOCK:A aa\n') - # Reading should fail - mock_instrument.a - @raises(AttributeError) -def test_enum_property_read_only(): +def test_enum_property_readonly_writing_fails(): class SillyEnum(Enum): a = 'aa' @@ -249,11 +272,21 @@ class EnumMock(MockInstrument): mock_instrument = EnumMock({'MOCK:A?':'aa'}) - # Reading should pass - eq_(mock_instrument.a, SillyEnum.a) - # Writing should fail mock_instrument.a = SillyEnum.a + +def test_enum_property_readonly_reading_passes(): + class SillyEnum(Enum): + a = 'aa' + + class EnumMock(MockInstrument): + a = enum_property('MOCK:A', SillyEnum, readonly=True) + + mock_instrument = EnumMock({'MOCK:A?':'aa'}) + + # Reading should pass + eq_(mock_instrument.a, SillyEnum.a) + eq_(mock_instrument.value, 'MOCK:A?\n') ## Unitless Property ## @@ -287,7 +320,16 @@ class UnitlessMock(MockInstrument): eq_(mock_inst.value, 'MOCK {:f}\n'.format(1)) @raises(AttributeError) -def test_unitless_property_write_only(): +def test_unitless_property_writeonly_reading_fails(): + class UnitlessMock(MockInstrument): + unitless_property = unitless_property('MOCK', writeonly=True) + + mock_inst = UnitlessMock() + + # Reading should fail + mock_inst.unitless_property + +def test_unitless_property_writeonly_writing_passes(): class UnitlessMock(MockInstrument): unitless_property = unitless_property('MOCK', writeonly=True) @@ -297,21 +339,24 @@ class UnitlessMock(MockInstrument): mock_inst.unitless_property = 1 eq_(mock_inst.value, 'MOCK {:e}\n'.format(1)) - # Reading should fail - mock_inst.unitless_property - @raises(AttributeError) -def test_unitless_property_read_only(): +def test_unitless_property_readonly_writing_fails(): class UnitlessMock(MockInstrument): unitless_property = unitless_property('MOCK', readonly=True) mock_inst = UnitlessMock({'MOCK?':'1'}) - # Reading should pass - eq_(mock_inst.unitless_property, 1) - # Writing should fail mock_inst.unitless_property = 1 + +def test_unitless_property_readonly_reading_passes(): + class UnitlessMock(MockInstrument): + unitless_property = unitless_property('MOCK', readonly=True) + + mock_inst = UnitlessMock({'MOCK?':'1'}) + + # Reading should pass + eq_(mock_inst.unitless_property, 1) ## Int Property Factories ## @@ -343,6 +388,45 @@ class IntMock(MockInstrument): mock_inst.int_property = 1 eq_(mock_inst.value, 'MOCK 1\n') + +@raises(AttributeError) +def test_int_property_writeonly_reading_fails(): + class IntMock(MockInstrument): + int_property = int_property('MOCK', writeonly=True) + + mock_inst = IntMock() + + # Reading should fail + mock_inst.int_property + +def test_int_property_writeonly_writing_passes(): + class IntMock(MockInstrument): + int_property = int_property('MOCK', writeonly=True) + + mock_inst = IntMock() + + # Writing should pass + mock_inst.int_property = 1 + eq_(mock_inst.value, 'MOCK {:d}\n'.format(1)) + +@raises(AttributeError) +def test_int_property_readonly_writing_fails(): + class IntMock(MockInstrument): + int_property = int_property('MOCK', readonly=True) + + mock_inst = IntMock({'MOCK?':'1'}) + + # Writing should fail + mock_inst.int_property = 1 + +def test_int_property_readonly_reading_passes(): + class IntMock(MockInstrument): + int_property = int_property('MOCK', readonly=True) + + mock_inst = IntMock({'MOCK?':'1'}) + + # Reading should pass + eq_(mock_inst.int_property, 1) ## Unitful Property ## @@ -394,7 +478,16 @@ class UnitfulMock(MockInstrument): mock_inst.unitful_property = 1 * pq.volt @raises(AttributeError) -def test_unitful_property_write_only(): +def test_unitful_property_writeonly_reading_fails(): + class UnitfulMock(MockInstrument): + unitful_property = unitful_property('MOCK', pq.hertz, writeonly=True) + + mock_inst = UnitfulMock() + + # Reading should fail + mock_inst.unitful_property + +def test_unitful_property_writeonly_writing_passes(): class UnitfulMock(MockInstrument): unitful_property = unitful_property('MOCK', pq.hertz, writeonly=True) @@ -404,22 +497,24 @@ class UnitfulMock(MockInstrument): mock_inst.unitful_property = 1 * pq.hertz eq_(mock_inst.value, 'MOCK {:e}\n'.format(1)) - # Reading should fail - mock_inst.unitful_property - @raises(AttributeError) -def test_unitful_property_read_only(): +def test_unitful_property_readonly_writing_fails(): class UnitfulMock(MockInstrument): unitful_property = unitful_property('MOCK', pq.hertz, readonly=True) mock_inst = UnitfulMock({'MOCK?':'1'}) - # Reading should pass - eq_(mock_inst.unitful_property, 1 * pq.hertz) - # Writing should fail mock_inst.unitful_property = 1 * pq.hertz - + +def test_unitful_property_readonly_reading_passes(): + class UnitfulMock(MockInstrument): + unitful_property = unitful_property('MOCK', pq.hertz, readonly=True) + + mock_inst = UnitfulMock({'MOCK?':'1'}) + + # Reading should pass + eq_(mock_inst.unitful_property, 1 * pq.hertz) ## String Property ## From afa219a580fa282fb0a611c333b3310add5059f5 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Fri, 25 Dec 2015 10:28:14 -0500 Subject: [PATCH 14/17] Same as last commit but for rproperty, and fix write only test --- .../tests/test_property_factories.py | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/instruments/instruments/tests/test_property_factories.py b/instruments/instruments/tests/test_property_factories.py index b883fe4f6..47d649bcf 100644 --- a/instruments/instruments/tests/test_property_factories.py +++ b/instruments/instruments/tests/test_property_factories.py @@ -79,7 +79,7 @@ def mockset(self, newval): eq_(mock_inst.mockproperty, 1) @raises(AttributeError) -def test_rproperty_readonly(): +def test_rproperty_readonly_writing_fails(): class Mock(MockInstrument): def __init__(self): self._value = 0 @@ -90,11 +90,23 @@ def mockset(self, newval): mockproperty = rproperty(fget=mockget, fset=mockset, readonly=True) mock_inst = Mock() - eq_(mock_inst.mockproperty, 0) # Reading should pass mock_inst.mockproperty = 1 # Writing should raise attr error + +def test_rproperty_readonly_reading_passes(): + class Mock(MockInstrument): + def __init__(self): + self._value = 0 + def mockget(self): + return self._value + def mockset(self, newval): + self._value = newval + mockproperty = rproperty(fget=mockget, fset=mockset, readonly=True) + + mock_inst = Mock() + eq_(mock_inst.mockproperty, 0) # Reading should pass @raises(AttributeError) -def test_rproperty_writeonly(): +def test_rproperty_writeonly_reading_fails(): class Mock(MockInstrument): def __init__(self): self._value = 0 @@ -102,11 +114,23 @@ def mockget(self): return self._value def mockset(self, newval): self._value = newval - mockproperty = rproperty(fget=mockget, fset=mockset, readonly=True) + mockproperty = rproperty(fget=mockget, fset=mockset, writeonly=True) mock_inst = Mock() - mock_inst.mockproperty = 1 eq_(mock_inst.mockproperty, 0) # Should raise attr error + +def test_rproperty_writeonly_writing_passes(): + class Mock(MockInstrument): + def __init__(self): + self._value = 0 + def mockget(self): + return self._value + def mockset(self, newval): + self._value = newval + mockproperty = rproperty(fget=mockget, fset=mockset, writeonly=True) + + mock_inst = Mock() + mock_inst.mockproperty = 1 @raises(ValueError) def test_rproperty_readonly_and_writeonly(): From c1bd91af7dcd7b31c4cf9f59266840b47248e472 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Fri, 25 Dec 2015 10:44:04 -0500 Subject: [PATCH 15/17] Remove lines that do not get executed --- .../tests/test_property_factories.py | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/instruments/instruments/tests/test_property_factories.py b/instruments/instruments/tests/test_property_factories.py index 47d649bcf..e262b42f7 100644 --- a/instruments/instruments/tests/test_property_factories.py +++ b/instruments/instruments/tests/test_property_factories.py @@ -83,11 +83,9 @@ def test_rproperty_readonly_writing_fails(): class Mock(MockInstrument): def __init__(self): self._value = 0 - def mockget(self): - return self._value - def mockset(self, newval): + def mockset(self, newval): # pragma: no cover self._value = newval - mockproperty = rproperty(fget=mockget, fset=mockset, readonly=True) + mockproperty = rproperty(fget=None, fset=mockset, readonly=True) mock_inst = Mock() mock_inst.mockproperty = 1 # Writing should raise attr error @@ -98,9 +96,7 @@ def __init__(self): self._value = 0 def mockget(self): return self._value - def mockset(self, newval): - self._value = newval - mockproperty = rproperty(fget=mockget, fset=mockset, readonly=True) + mockproperty = rproperty(fget=mockget, fset=None, readonly=True) mock_inst = Mock() eq_(mock_inst.mockproperty, 0) # Reading should pass @@ -110,11 +106,9 @@ def test_rproperty_writeonly_reading_fails(): class Mock(MockInstrument): def __init__(self): self._value = 0 - def mockget(self): + def mockget(self): # pragma: no cover return self._value - def mockset(self, newval): - self._value = newval - mockproperty = rproperty(fget=mockget, fset=mockset, writeonly=True) + mockproperty = rproperty(fget=mockget, fset=None, writeonly=True) mock_inst = Mock() eq_(mock_inst.mockproperty, 0) # Should raise attr error @@ -123,11 +117,9 @@ def test_rproperty_writeonly_writing_passes(): class Mock(MockInstrument): def __init__(self): self._value = 0 - def mockget(self): - return self._value def mockset(self, newval): self._value = newval - mockproperty = rproperty(fget=mockget, fset=mockset, writeonly=True) + mockproperty = rproperty(fget=None, fset=mockset, writeonly=True) mock_inst = Mock() mock_inst.mockproperty = 1 From b8b7c5ea07492a743e0958b5e1b9bfd36e1a4242 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Fri, 25 Dec 2015 10:49:53 -0500 Subject: [PATCH 16/17] Removed a bunch of unneeded line comments --- .../tests/test_property_factories.py | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/instruments/instruments/tests/test_property_factories.py b/instruments/instruments/tests/test_property_factories.py index e262b42f7..92234c322 100644 --- a/instruments/instruments/tests/test_property_factories.py +++ b/instruments/instruments/tests/test_property_factories.py @@ -88,7 +88,7 @@ def mockset(self, newval): # pragma: no cover mockproperty = rproperty(fget=None, fset=mockset, readonly=True) mock_inst = Mock() - mock_inst.mockproperty = 1 # Writing should raise attr error + mock_inst.mockproperty = 1 def test_rproperty_readonly_reading_passes(): class Mock(MockInstrument): @@ -99,7 +99,7 @@ def mockget(self): mockproperty = rproperty(fget=mockget, fset=None, readonly=True) mock_inst = Mock() - eq_(mock_inst.mockproperty, 0) # Reading should pass + eq_(mock_inst.mockproperty, 0) @raises(AttributeError) def test_rproperty_writeonly_reading_fails(): @@ -111,7 +111,7 @@ def mockget(self): # pragma: no cover mockproperty = rproperty(fget=mockget, fset=None, writeonly=True) mock_inst = Mock() - eq_(mock_inst.mockproperty, 0) # Should raise attr error + eq_(mock_inst.mockproperty, 0) def test_rproperty_writeonly_writing_passes(): class Mock(MockInstrument): @@ -262,7 +262,6 @@ class EnumMock(MockInstrument): mock_instrument = EnumMock() - # Reading should fail mock_instrument.a def test_enum_property_writeonly_writing_passes(): @@ -274,7 +273,6 @@ class EnumMock(MockInstrument): mock_instrument = EnumMock() - # Writing should pass mock_instrument.a = SillyEnum.a eq_(mock_instrument.value, 'MOCK:A aa\n') @@ -288,7 +286,6 @@ class EnumMock(MockInstrument): mock_instrument = EnumMock({'MOCK:A?':'aa'}) - # Writing should fail mock_instrument.a = SillyEnum.a def test_enum_property_readonly_reading_passes(): @@ -300,7 +297,6 @@ class EnumMock(MockInstrument): mock_instrument = EnumMock({'MOCK:A?':'aa'}) - # Reading should pass eq_(mock_instrument.a, SillyEnum.a) eq_(mock_instrument.value, 'MOCK:A?\n') @@ -342,7 +338,6 @@ class UnitlessMock(MockInstrument): mock_inst = UnitlessMock() - # Reading should fail mock_inst.unitless_property def test_unitless_property_writeonly_writing_passes(): @@ -351,7 +346,6 @@ class UnitlessMock(MockInstrument): mock_inst = UnitlessMock() - # Writing should pass mock_inst.unitless_property = 1 eq_(mock_inst.value, 'MOCK {:e}\n'.format(1)) @@ -362,7 +356,6 @@ class UnitlessMock(MockInstrument): mock_inst = UnitlessMock({'MOCK?':'1'}) - # Writing should fail mock_inst.unitless_property = 1 def test_unitless_property_readonly_reading_passes(): @@ -371,7 +364,6 @@ class UnitlessMock(MockInstrument): mock_inst = UnitlessMock({'MOCK?':'1'}) - # Reading should pass eq_(mock_inst.unitless_property, 1) ## Int Property Factories ## @@ -412,7 +404,6 @@ class IntMock(MockInstrument): mock_inst = IntMock() - # Reading should fail mock_inst.int_property def test_int_property_writeonly_writing_passes(): @@ -421,7 +412,6 @@ class IntMock(MockInstrument): mock_inst = IntMock() - # Writing should pass mock_inst.int_property = 1 eq_(mock_inst.value, 'MOCK {:d}\n'.format(1)) @@ -432,7 +422,6 @@ class IntMock(MockInstrument): mock_inst = IntMock({'MOCK?':'1'}) - # Writing should fail mock_inst.int_property = 1 def test_int_property_readonly_reading_passes(): @@ -441,7 +430,6 @@ class IntMock(MockInstrument): mock_inst = IntMock({'MOCK?':'1'}) - # Reading should pass eq_(mock_inst.int_property, 1) ## Unitful Property ## @@ -500,7 +488,6 @@ class UnitfulMock(MockInstrument): mock_inst = UnitfulMock() - # Reading should fail mock_inst.unitful_property def test_unitful_property_writeonly_writing_passes(): @@ -509,7 +496,6 @@ class UnitfulMock(MockInstrument): mock_inst = UnitfulMock() - # Writing should pass mock_inst.unitful_property = 1 * pq.hertz eq_(mock_inst.value, 'MOCK {:e}\n'.format(1)) @@ -520,7 +506,6 @@ class UnitfulMock(MockInstrument): mock_inst = UnitfulMock({'MOCK?':'1'}) - # Writing should fail mock_inst.unitful_property = 1 * pq.hertz def test_unitful_property_readonly_reading_passes(): @@ -529,7 +514,6 @@ class UnitfulMock(MockInstrument): mock_inst = UnitfulMock({'MOCK?':'1'}) - # Reading should pass eq_(mock_inst.unitful_property, 1 * pq.hertz) ## String Property ## From 437fd0da8a23a7fa1f4268289c704288e0ff3fa4 Mon Sep 17 00:00:00 2001 From: Steven Casagrande Date: Fri, 25 Dec 2015 20:15:19 -0500 Subject: [PATCH 17/17] Add a format code test for int_property --- instruments/instruments/tests/test_property_factories.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/instruments/instruments/tests/test_property_factories.py b/instruments/instruments/tests/test_property_factories.py index 92234c322..a7fcabaec 100644 --- a/instruments/instruments/tests/test_property_factories.py +++ b/instruments/instruments/tests/test_property_factories.py @@ -431,6 +431,15 @@ class IntMock(MockInstrument): mock_inst = IntMock({'MOCK?':'1'}) eq_(mock_inst.int_property, 1) + +def test_int_property_format_code(): + class IntMock(MockInstrument): + int_property = int_property('MOCK', format_code='{:e}') + + mock_inst = IntMock() + + mock_inst.int_property = 1 + eq_(mock_inst.value, 'MOCK {:e}\n'.format(1)) ## Unitful Property ##