From 1c6148fadec0abac09897f5488475b25bef43730 Mon Sep 17 00:00:00 2001 From: Matthew Rankin Date: Tue, 22 Jul 2014 18:16:12 -0500 Subject: [PATCH 1/6] Remove superfluous EOL whitespace in agilentMSOX3024A.py --- ivi/agilent/agilentMSOX3024A.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ivi/agilent/agilentMSOX3024A.py b/ivi/agilent/agilentMSOX3024A.py index f432f5ad..94f14352 100644 --- a/ivi/agilent/agilentMSOX3024A.py +++ b/ivi/agilent/agilentMSOX3024A.py @@ -28,17 +28,15 @@ class agilentMSOX3024A(agilent3000A): "Agilent InfiniiVision MSOX3024A IVI oscilloscope driver" - + def __init__(self, *args, **kwargs): self.__dict__.setdefault('_instrument_id', 'MSO-X 3024A') - + super(agilentMSOX3024A, self).__init__(*args, **kwargs) - + self._analog_channel_count = 4 self._digital_channel_count = 16 self._channel_count = self._analog_channel_count + self._digital_channel_count self._bandwidth = 200e6 - + self._init_channels() - - From 4f8a071cee83e69e68a5e2d1e545a44cbb4dcab8 Mon Sep 17 00:00:00 2001 From: Matthew Rankin Date: Wed, 23 Jul 2014 13:02:55 -0500 Subject: [PATCH 2/6] First cut at unit-tests (UTs) for agilentMSOX3024A.py --- ivi/agilent/test/test_agilentMSOX3024A.py | 140 ++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 ivi/agilent/test/test_agilentMSOX3024A.py diff --git a/ivi/agilent/test/test_agilentMSOX3024A.py b/ivi/agilent/test/test_agilentMSOX3024A.py new file mode 100644 index 00000000..a080fd61 --- /dev/null +++ b/ivi/agilent/test/test_agilentMSOX3024A.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2014 The python-ivi developers. All rights reserved. +# Project site: https://github.com/python-ivi/python-ivi +# Use of this source code is governed by a MIT-style license that +# can be found in the COPYING file for the project. +"""Unit tests for agilentMSOX3024A.py. +""" + +import unittest + +from ivi.agilent.agilentMSOX3024A import agilentMSOX3024A + + +class TestAgilentMSOX3024A(unittest.TestCase): + + def setUp(self): # NOQA + self.scope = agilentMSOX3024A() + + def test_identity_description(self): + self.assertEqual( + self.scope._identity_description, + 'Agilent InfiniiVision 3000A X-series IVI oscilloscope driver') + + def test_identity_support_instrument_model(self): + self.assertIn('MSOX3024A', + self.scope._identity_supported_instrument_models) + + def test_analog_channel_count(self): + self.assertEqual(self.scope._analog_channel_count, 4) + + def test_analog_channel_name(self): + analog_channel_names = ['channel{}'.format(x) for x in range(1, 5)] + self.assertEqual( + self.scope._analog_channel_name, + analog_channel_names) + + def test_digital_channel_count(self): + self.assertEqual(self.scope._digital_channel_count, 16) + + def test_digital_channel_name(self): + digital_channel_names = ['digital{}'.format(x) for x in range(16)] + self.assertEqual( + self.scope._digital_channel_name, + digital_channel_names) + + def test_channel_count(self): + self.assertEqual(self.scope._channel_count, 20) + + def test_bandwidth(self): + self.assertEqual(self.scope._bandwidth, 200e6) + + def test_wavegen_output_count(self): + self.assertEqual(self.scope._output_count, 1) + + def test_output_standard_waveform_mapping(self): + waveforms = ('sine', 'square', 'ramp_up', 'pulse', 'noise', + 'dc', 'sinc', 'exprise', 'expfall', 'cardiac', 'gaussian') + for waveform in waveforms: + self.assertIn( + waveform, self.scope._output_standard_waveform_mapping) + + def test_horizontal_divisions(self): + self.assertEqual(10, self.scope._horizontal_divisions) + + def test_vertical_divisions(self): + self.assertEqual(8, self.scope._vertical_divisions) + + def test_display_screenshot_image_format_mapping(self): + image_formats = ('bmp', 'bmp24', 'bmp8', 'png', 'png24') + for image_format in image_formats: + self.assertIn(image_format, + self.scope._display_screenshot_image_format_mapping) + + def test_output_name(self): + self.assertEqual(self.scope._output_name, ['wgen']) + + def test_output_operation_mode(self): + self.assertEqual(self.scope._output_operation_mode, ['continuous']) + + def test_output_enabled(self): + self.assertEqual(self.scope._output_enabled, [False]) + + def test_output_impedance(self): + self.assertEqual(self.scope._output_impedance, [50]) + + def test_output_mode(self): + self.assertEqual(self.scope._output_mode, ['function']) + + def test_output_reference_clock_source(self): + self.assertEqual(self.scope._output_reference_clock_source, ['']) + + def test_get_output_operation_mode(self): + self.assertEqual(self.scope._get_output_operation_mode(0), + 'continuous') + + def test_set_output_operation_mode_valid(self): + # Make sure an exception isn't raised for a valid operation mode + self.scope._set_output_operation_mode(0, 'burst') + + def test_set_output_operation_mode_to_invalid_mode(self): + self.assertRaises( + TypeError, + self.scope._set_output_operation_mode, + (0, 'trash_mode')) + + def test_get_output_enabled_while_simulating_driver_operation(self): + # TODO(mdr) Need to test _get_output_enabled() using mocks/spies when + # self.scope._driver_operation_simulate = False + self.scope._driver_operation_simulate = True + self.assertEqual(self.scope._get_output_enabled(0), False) + + def test_set_output_enabled_while_simulating_driver_operation(self): + # TODO(mdr) Need to test _set_output_enabled() using mocks/spies when + # self.scope._driver_operation_simulate = False + self.scope._driver_operation_simulate = True + # Make sure an exception isn't raised + self.scope._set_output_enabled(0, True) + + def test_get_output_impedance_while_simulating_driver_operation(self): + # TODO(mdr) Need to test _get_output_impedance() using mocks/spies when + # self.scope._driver_operation_simulate = False + self.scope._driver_operation_simulate = True + self.assertEqual(self.scope._get_output_impedance(0), 50) + + def test_set_output_impedance_while_simulating_driver_operation(self): + # TODO(mdr) Need to test _set_output_impedance() using mocks/spies when + # self.scope._driver_operation_simulate = False + self.scope._driver_operation_simulate = True + # Make sure an exception isn't raised + self.scope._set_output_impedance(0, 1000000) + + def test_output_impedance_must_be_set_to_valid_impedance(self): + self.scope._driver_operation_simulate = True + invalid_impedances = (25, 75, 100, 1000001) + for invalid_impedance in invalid_impedances: + self.assertRaises( + Exception, + self.scope._set_output_impedance, + 0, + invalid_impedance) From 19fbefd4bd1575e5cec836d3de16b4eb46578769 Mon Sep 17 00:00:00 2001 From: Matthew Rankin Date: Thu, 24 Jul 2014 08:33:50 -0500 Subject: [PATCH 3/6] Add unit tests with mocks for _ask and _write. Test failing! By using mocks, we don't have to set self._driver_operation_simulate to True in order to execute the tests. This brought to light what appears to be an error in the _get_output_enabled() in agilent2000A.py --- ivi/agilent/test/test_agilentMSOX3024A.py | 29 +++++++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/ivi/agilent/test/test_agilentMSOX3024A.py b/ivi/agilent/test/test_agilentMSOX3024A.py index a080fd61..0b5b4c38 100644 --- a/ivi/agilent/test/test_agilentMSOX3024A.py +++ b/ivi/agilent/test/test_agilentMSOX3024A.py @@ -7,6 +7,7 @@ """ import unittest +from mock import MagicMock from ivi.agilent.agilentMSOX3024A import agilentMSOX3024A @@ -104,18 +105,34 @@ def test_set_output_operation_mode_to_invalid_mode(self): (0, 'trash_mode')) def test_get_output_enabled_while_simulating_driver_operation(self): - # TODO(mdr) Need to test _get_output_enabled() using mocks/spies when - # self.scope._driver_operation_simulate = False self.scope._driver_operation_simulate = True self.assertEqual(self.scope._get_output_enabled(0), False) + def test_get_output_enabled_when_scope_query_returns_0(self): + self.scope._ask = MagicMock(return_value='0') + self.assertEqual(self.scope._get_output_enabled(0), False) + self.scope._ask.assert_called_with( + ':{}:output?'.format(self.scope._output_name[0])) + + def test_get_output_enabled_when_scope_query_returns_1(self): + self.scope._ask = MagicMock(return_value='1') + self.assertEqual(self.scope._get_output_enabled(0), True) + self.scope._ask.assert_called_with( + ':{}:output?'.format(self.scope._output_name[0])) + def test_set_output_enabled_while_simulating_driver_operation(self): - # TODO(mdr) Need to test _set_output_enabled() using mocks/spies when - # self.scope._driver_operation_simulate = False self.scope._driver_operation_simulate = True # Make sure an exception isn't raised self.scope._set_output_enabled(0, True) + def test_set_output_enabled_without_simulating_driver_operation(self): + self.scope._write = MagicMock() + for is_output_enabled in (True, False): + self.scope._set_output_enabled(0, is_output_enabled) + self.scope._ask = MagicMock(return_value=is_output_enabled) + self.assertEqual(self.scope._get_output_enabled(0), + is_output_enabled) + def test_get_output_impedance_while_simulating_driver_operation(self): # TODO(mdr) Need to test _get_output_impedance() using mocks/spies when # self.scope._driver_operation_simulate = False @@ -126,8 +143,10 @@ def test_set_output_impedance_while_simulating_driver_operation(self): # TODO(mdr) Need to test _set_output_impedance() using mocks/spies when # self.scope._driver_operation_simulate = False self.scope._driver_operation_simulate = True - # Make sure an exception isn't raised + # Make sure an exception isn't raised when setting a valid output + # impedance self.scope._set_output_impedance(0, 1000000) + self.scope._set_output_impedance(0, 50) def test_output_impedance_must_be_set_to_valid_impedance(self): self.scope._driver_operation_simulate = True From 8ddcdc3c3533a72f327c89354aa47d807c41c0dc Mon Sep 17 00:00:00 2001 From: Matthew Rankin Date: Thu, 24 Jul 2014 08:51:35 -0500 Subject: [PATCH 4/6] Fixes #14 _get_output_enabled() return --- ivi/agilent/agilent2000A.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ivi/agilent/agilent2000A.py b/ivi/agilent/agilent2000A.py index 2d5259eb..ec857211 100644 --- a/ivi/agilent/agilent2000A.py +++ b/ivi/agilent/agilent2000A.py @@ -120,7 +120,7 @@ def _get_output_enabled(self, index): index = ivi.get_index(self._output_name, index) if not self._driver_operation_simulate and not self._get_cache_valid(index=index): resp = self._ask(":%s:output?" % self._output_name[index]) - self._output_standard_waveform_amplitude[index] = bool(int(resp)) + self._output_enabled[index] = bool(int(resp)) self._set_cache_valid(index=index) return self._output_enabled[index] From 16b9a5fa55b4001c5f8976fa1da4e5d61d57c2ef Mon Sep 17 00:00:00 2001 From: Matthew Rankin Date: Fri, 25 Jul 2014 08:31:21 -0500 Subject: [PATCH 5/6] Add UTs with mocks for output_impedance --- ivi/agilent/test/test_agilentMSOX3024A.py | 28 +++++++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/ivi/agilent/test/test_agilentMSOX3024A.py b/ivi/agilent/test/test_agilentMSOX3024A.py index 0b5b4c38..a3d2d7bc 100644 --- a/ivi/agilent/test/test_agilentMSOX3024A.py +++ b/ivi/agilent/test/test_agilentMSOX3024A.py @@ -132,24 +132,42 @@ def test_set_output_enabled_without_simulating_driver_operation(self): self.scope._ask = MagicMock(return_value=is_output_enabled) self.assertEqual(self.scope._get_output_enabled(0), is_output_enabled) + self.scope._write.assert_called_with( + ':{}:output {}'.format('wgen', int(is_output_enabled))) def test_get_output_impedance_while_simulating_driver_operation(self): - # TODO(mdr) Need to test _get_output_impedance() using mocks/spies when - # self.scope._driver_operation_simulate = False self.scope._driver_operation_simulate = True self.assertEqual(self.scope._get_output_impedance(0), 50) + def test_get_output_impedance_for_fifty_ohms(self): + self.scope._ask = MagicMock(return_value='FIFT') + self.assertEqual(self.scope._get_output_impedance(0), 50) + self.scope._ask.assert_called_with( + ':{}:output:load?'.format('wgen')) + + def test_get_output_impedance_for_one_megaohm(self): + self.scope._ask = MagicMock(return_value='ONEM') + self.assertEqual(self.scope._get_output_impedance(0), 1000000) + self.scope._ask.assert_called_with( + ':{}:output:load?'.format('wgen')) + def test_set_output_impedance_while_simulating_driver_operation(self): - # TODO(mdr) Need to test _set_output_impedance() using mocks/spies when - # self.scope._driver_operation_simulate = False self.scope._driver_operation_simulate = True # Make sure an exception isn't raised when setting a valid output # impedance self.scope._set_output_impedance(0, 1000000) self.scope._set_output_impedance(0, 50) + def test_set_output_impedance(self): + self.scope._write = MagicMock() + for impedance, load in zip( + (50, 1000000), ('fifty', 'onemeg')): + self.scope._set_output_impedance(0, impedance) + self.assertEqual(self.scope._output_impedance[0], impedance) + self.scope._write.assert_called_with( + ':{}:output:load {}'.format('wgen', load)) + def test_output_impedance_must_be_set_to_valid_impedance(self): - self.scope._driver_operation_simulate = True invalid_impedances = (25, 75, 100, 1000001) for invalid_impedance in invalid_impedances: self.assertRaises( From 089c724d11870abeb40943dc99853f6e525dedde Mon Sep 17 00:00:00 2001 From: Matthew Rankin Date: Thu, 31 Jul 2014 08:55:29 -0500 Subject: [PATCH 6/6] Add UTs for get/set output_mode and output_reference_clock_source --- ivi/agilent/test/test_agilentMSOX3024A.py | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/ivi/agilent/test/test_agilentMSOX3024A.py b/ivi/agilent/test/test_agilentMSOX3024A.py index a3d2d7bc..ffe3e6dc 100644 --- a/ivi/agilent/test/test_agilentMSOX3024A.py +++ b/ivi/agilent/test/test_agilentMSOX3024A.py @@ -175,3 +175,32 @@ def test_output_impedance_must_be_set_to_valid_impedance(self): self.scope._set_output_impedance, 0, invalid_impedance) + + def test_get_output_mode(self): + self.assertEqual(self.scope._get_output_mode(0), 'function') + + def test_set_output_mode(self): + for bad_mode in ('trash', 'not-function'): + self.assertRaises( + Exception, + self.scope._set_output_mode, + 0, + bad_mode) + # Make sure an exception isn't raised when setting a valid output + # mode + self.scope._set_output_mode(0, 'function') + self.assertEqual(self.scope._get_output_mode(0), 'function') + + def test_get_output_reference_clock_source(self): + self.assertEqual( + self.scope._get_output_reference_clock_source(0), + '') + + def test_set_output_reference_clock_source(self): + # FIXME(mdr): Seems strange that no matter what value you pass into the + # _set_output_reference_clock_source function, the value is set to + # 'internal'. Should the fcn in agilent2000A.py change? + self.scope._set_output_reference_clock_source(0, 'blah') + self.assertEqual( + self.scope._get_output_reference_clock_source(0), + 'internal')