Can you use mock_open to simulate serial connections?










1















Morning folks,



I'm trying to get a few unit tests going in Python to confirm my code is working, but I'm having a real hard time getting a Mock anything to fit into my test cases. I'm new to Python unit testing, so this has been a trying week thus far.



The summary of the program is I'm attempting to do serial control of a commercial monitor I got my hands on and I thought I'd use it as a chance to finally use Python for something rather than just falling back on one of the other languages I know. I've got pyserial going, but before I start shoving a ton of commands out to the TV I'd like to learn the unittest part so I can write for my expected outputs and inputs.



I've tried using a library called dummyserial, but it didn't seem to be recognising the output I was sending. I thought I'd give mock_open a try as I've seen it works like a standard IO as well, but it just isn't picking up on the calls either. Samples of the code involved:



def testSendCmd(self):
powerCheck = '01:>4r'.format(SharpCodes['POWER'], SharpCodes['CHECK']).encode('utf-8')
read_text = 'Stuffr'
mo = mock_open(read_data=read_text)
mo.in_waiting = len(read_text)
with patch('__main__.open', mo):
with open('./serial', 'a+b') as com:
tv = SharpTV(com=com, TVID=999, tvInput = 'DVI')
tv.sendCmd(SharpCodes['POWER'], SharpCodes['CHECK'])
com.write(b'some junk')
print(mo.mock_calls)
mo().write.assert_called_with('01:>4r'.format(SharpCodes['POWER'], SharpCodes['CHECK']).encode('utf-8'))


And in the SharpTV class, the function in question:



def sendCmd(self, type, msg):
sent = self.com.write('01:>4r'.format(type,msg).encode('utf-8'))
print('01:>4r'.format(type,msg).encode('utf-8'))


Obviously, I'm attempting to control a Sharp TV. I know the commands are correct, that isn't the issue. The issue is just the testing. According to documentation on the mock_open page, calling mo.mock_calls should return some data that a call was made, but I'm getting just an empty set of 's even in spite of the blatantly wrong com.write(b'some junk'), and mo().write.assert_called_with(...) is returning with an assert error because it isn't detecting the write from within sendCmd. What's really bothering me is I can do the examples from the mock_open section in interactive mode and it works as expected.



I'm missing something, I just don't know what. I'd like help getting either dummyserial working, or mock_open.










share|improve this question
























  • What's the type of self.com? Whatever type that is, that's the type you need to patch out.

    – Matt Messersmith
    Nov 15 '18 at 21:35











  • It's technically a serial.Serial() instance (pyserial), but besides in_waiting there's not a lot of difference between a read() on pyserial and a read() on a standard open(). At least not how I'm using it. Changing out the patch, I've got mostly the same code except the following changes: mo = mock_opening(read_data=read_text) with patch('serial.Serial', mo): with serial.Serial() as com: tv = SharpTV(com=com...)

    – Feynt
    Nov 16 '18 at 13:10












  • The problem is that you're patching out the builtin open, which may or may not be what you need to be mocking. Why not just patch the com object and be done with it? Furthermore, that function is so simple that it hardly warrants a test...especially if you're going to mock out the write operation...

    – Matt Messersmith
    Nov 16 '18 at 14:12












  • Digging into dummyserial I found that it's decoding my input back into a string and checking against my dictionary for an actual string versus a byte encoded string. I've adjusted that and it seems like it's working for me now. I have more tests to do beyond this simple sendCmd, but I wanted to make sure I could at least get this working before moving onto (slightly) harder things like testing TV status codes loaded from a config file.

    – Feynt
    Nov 16 '18 at 14:18
















1















Morning folks,



I'm trying to get a few unit tests going in Python to confirm my code is working, but I'm having a real hard time getting a Mock anything to fit into my test cases. I'm new to Python unit testing, so this has been a trying week thus far.



The summary of the program is I'm attempting to do serial control of a commercial monitor I got my hands on and I thought I'd use it as a chance to finally use Python for something rather than just falling back on one of the other languages I know. I've got pyserial going, but before I start shoving a ton of commands out to the TV I'd like to learn the unittest part so I can write for my expected outputs and inputs.



I've tried using a library called dummyserial, but it didn't seem to be recognising the output I was sending. I thought I'd give mock_open a try as I've seen it works like a standard IO as well, but it just isn't picking up on the calls either. Samples of the code involved:



def testSendCmd(self):
powerCheck = '01:>4r'.format(SharpCodes['POWER'], SharpCodes['CHECK']).encode('utf-8')
read_text = 'Stuffr'
mo = mock_open(read_data=read_text)
mo.in_waiting = len(read_text)
with patch('__main__.open', mo):
with open('./serial', 'a+b') as com:
tv = SharpTV(com=com, TVID=999, tvInput = 'DVI')
tv.sendCmd(SharpCodes['POWER'], SharpCodes['CHECK'])
com.write(b'some junk')
print(mo.mock_calls)
mo().write.assert_called_with('01:>4r'.format(SharpCodes['POWER'], SharpCodes['CHECK']).encode('utf-8'))


And in the SharpTV class, the function in question:



def sendCmd(self, type, msg):
sent = self.com.write('01:>4r'.format(type,msg).encode('utf-8'))
print('01:>4r'.format(type,msg).encode('utf-8'))


Obviously, I'm attempting to control a Sharp TV. I know the commands are correct, that isn't the issue. The issue is just the testing. According to documentation on the mock_open page, calling mo.mock_calls should return some data that a call was made, but I'm getting just an empty set of 's even in spite of the blatantly wrong com.write(b'some junk'), and mo().write.assert_called_with(...) is returning with an assert error because it isn't detecting the write from within sendCmd. What's really bothering me is I can do the examples from the mock_open section in interactive mode and it works as expected.



I'm missing something, I just don't know what. I'd like help getting either dummyserial working, or mock_open.










share|improve this question
























  • What's the type of self.com? Whatever type that is, that's the type you need to patch out.

    – Matt Messersmith
    Nov 15 '18 at 21:35











  • It's technically a serial.Serial() instance (pyserial), but besides in_waiting there's not a lot of difference between a read() on pyserial and a read() on a standard open(). At least not how I'm using it. Changing out the patch, I've got mostly the same code except the following changes: mo = mock_opening(read_data=read_text) with patch('serial.Serial', mo): with serial.Serial() as com: tv = SharpTV(com=com...)

    – Feynt
    Nov 16 '18 at 13:10












  • The problem is that you're patching out the builtin open, which may or may not be what you need to be mocking. Why not just patch the com object and be done with it? Furthermore, that function is so simple that it hardly warrants a test...especially if you're going to mock out the write operation...

    – Matt Messersmith
    Nov 16 '18 at 14:12












  • Digging into dummyserial I found that it's decoding my input back into a string and checking against my dictionary for an actual string versus a byte encoded string. I've adjusted that and it seems like it's working for me now. I have more tests to do beyond this simple sendCmd, but I wanted to make sure I could at least get this working before moving onto (slightly) harder things like testing TV status codes loaded from a config file.

    – Feynt
    Nov 16 '18 at 14:18














1












1








1








Morning folks,



I'm trying to get a few unit tests going in Python to confirm my code is working, but I'm having a real hard time getting a Mock anything to fit into my test cases. I'm new to Python unit testing, so this has been a trying week thus far.



The summary of the program is I'm attempting to do serial control of a commercial monitor I got my hands on and I thought I'd use it as a chance to finally use Python for something rather than just falling back on one of the other languages I know. I've got pyserial going, but before I start shoving a ton of commands out to the TV I'd like to learn the unittest part so I can write for my expected outputs and inputs.



I've tried using a library called dummyserial, but it didn't seem to be recognising the output I was sending. I thought I'd give mock_open a try as I've seen it works like a standard IO as well, but it just isn't picking up on the calls either. Samples of the code involved:



def testSendCmd(self):
powerCheck = '01:>4r'.format(SharpCodes['POWER'], SharpCodes['CHECK']).encode('utf-8')
read_text = 'Stuffr'
mo = mock_open(read_data=read_text)
mo.in_waiting = len(read_text)
with patch('__main__.open', mo):
with open('./serial', 'a+b') as com:
tv = SharpTV(com=com, TVID=999, tvInput = 'DVI')
tv.sendCmd(SharpCodes['POWER'], SharpCodes['CHECK'])
com.write(b'some junk')
print(mo.mock_calls)
mo().write.assert_called_with('01:>4r'.format(SharpCodes['POWER'], SharpCodes['CHECK']).encode('utf-8'))


And in the SharpTV class, the function in question:



def sendCmd(self, type, msg):
sent = self.com.write('01:>4r'.format(type,msg).encode('utf-8'))
print('01:>4r'.format(type,msg).encode('utf-8'))


Obviously, I'm attempting to control a Sharp TV. I know the commands are correct, that isn't the issue. The issue is just the testing. According to documentation on the mock_open page, calling mo.mock_calls should return some data that a call was made, but I'm getting just an empty set of 's even in spite of the blatantly wrong com.write(b'some junk'), and mo().write.assert_called_with(...) is returning with an assert error because it isn't detecting the write from within sendCmd. What's really bothering me is I can do the examples from the mock_open section in interactive mode and it works as expected.



I'm missing something, I just don't know what. I'd like help getting either dummyserial working, or mock_open.










share|improve this question
















Morning folks,



I'm trying to get a few unit tests going in Python to confirm my code is working, but I'm having a real hard time getting a Mock anything to fit into my test cases. I'm new to Python unit testing, so this has been a trying week thus far.



The summary of the program is I'm attempting to do serial control of a commercial monitor I got my hands on and I thought I'd use it as a chance to finally use Python for something rather than just falling back on one of the other languages I know. I've got pyserial going, but before I start shoving a ton of commands out to the TV I'd like to learn the unittest part so I can write for my expected outputs and inputs.



I've tried using a library called dummyserial, but it didn't seem to be recognising the output I was sending. I thought I'd give mock_open a try as I've seen it works like a standard IO as well, but it just isn't picking up on the calls either. Samples of the code involved:



def testSendCmd(self):
powerCheck = '01:>4r'.format(SharpCodes['POWER'], SharpCodes['CHECK']).encode('utf-8')
read_text = 'Stuffr'
mo = mock_open(read_data=read_text)
mo.in_waiting = len(read_text)
with patch('__main__.open', mo):
with open('./serial', 'a+b') as com:
tv = SharpTV(com=com, TVID=999, tvInput = 'DVI')
tv.sendCmd(SharpCodes['POWER'], SharpCodes['CHECK'])
com.write(b'some junk')
print(mo.mock_calls)
mo().write.assert_called_with('01:>4r'.format(SharpCodes['POWER'], SharpCodes['CHECK']).encode('utf-8'))


And in the SharpTV class, the function in question:



def sendCmd(self, type, msg):
sent = self.com.write('01:>4r'.format(type,msg).encode('utf-8'))
print('01:>4r'.format(type,msg).encode('utf-8'))


Obviously, I'm attempting to control a Sharp TV. I know the commands are correct, that isn't the issue. The issue is just the testing. According to documentation on the mock_open page, calling mo.mock_calls should return some data that a call was made, but I'm getting just an empty set of 's even in spite of the blatantly wrong com.write(b'some junk'), and mo().write.assert_called_with(...) is returning with an assert error because it isn't detecting the write from within sendCmd. What's really bothering me is I can do the examples from the mock_open section in interactive mode and it works as expected.



I'm missing something, I just don't know what. I'd like help getting either dummyserial working, or mock_open.







python python-3.x python-unittest pyserial






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 15 '18 at 20:31









Torxed

13.8k105790




13.8k105790










asked Nov 15 '18 at 20:27









FeyntFeynt

1316




1316












  • What's the type of self.com? Whatever type that is, that's the type you need to patch out.

    – Matt Messersmith
    Nov 15 '18 at 21:35











  • It's technically a serial.Serial() instance (pyserial), but besides in_waiting there's not a lot of difference between a read() on pyserial and a read() on a standard open(). At least not how I'm using it. Changing out the patch, I've got mostly the same code except the following changes: mo = mock_opening(read_data=read_text) with patch('serial.Serial', mo): with serial.Serial() as com: tv = SharpTV(com=com...)

    – Feynt
    Nov 16 '18 at 13:10












  • The problem is that you're patching out the builtin open, which may or may not be what you need to be mocking. Why not just patch the com object and be done with it? Furthermore, that function is so simple that it hardly warrants a test...especially if you're going to mock out the write operation...

    – Matt Messersmith
    Nov 16 '18 at 14:12












  • Digging into dummyserial I found that it's decoding my input back into a string and checking against my dictionary for an actual string versus a byte encoded string. I've adjusted that and it seems like it's working for me now. I have more tests to do beyond this simple sendCmd, but I wanted to make sure I could at least get this working before moving onto (slightly) harder things like testing TV status codes loaded from a config file.

    – Feynt
    Nov 16 '18 at 14:18


















  • What's the type of self.com? Whatever type that is, that's the type you need to patch out.

    – Matt Messersmith
    Nov 15 '18 at 21:35











  • It's technically a serial.Serial() instance (pyserial), but besides in_waiting there's not a lot of difference between a read() on pyserial and a read() on a standard open(). At least not how I'm using it. Changing out the patch, I've got mostly the same code except the following changes: mo = mock_opening(read_data=read_text) with patch('serial.Serial', mo): with serial.Serial() as com: tv = SharpTV(com=com...)

    – Feynt
    Nov 16 '18 at 13:10












  • The problem is that you're patching out the builtin open, which may or may not be what you need to be mocking. Why not just patch the com object and be done with it? Furthermore, that function is so simple that it hardly warrants a test...especially if you're going to mock out the write operation...

    – Matt Messersmith
    Nov 16 '18 at 14:12












  • Digging into dummyserial I found that it's decoding my input back into a string and checking against my dictionary for an actual string versus a byte encoded string. I've adjusted that and it seems like it's working for me now. I have more tests to do beyond this simple sendCmd, but I wanted to make sure I could at least get this working before moving onto (slightly) harder things like testing TV status codes loaded from a config file.

    – Feynt
    Nov 16 '18 at 14:18

















What's the type of self.com? Whatever type that is, that's the type you need to patch out.

– Matt Messersmith
Nov 15 '18 at 21:35





What's the type of self.com? Whatever type that is, that's the type you need to patch out.

– Matt Messersmith
Nov 15 '18 at 21:35













It's technically a serial.Serial() instance (pyserial), but besides in_waiting there's not a lot of difference between a read() on pyserial and a read() on a standard open(). At least not how I'm using it. Changing out the patch, I've got mostly the same code except the following changes: mo = mock_opening(read_data=read_text) with patch('serial.Serial', mo): with serial.Serial() as com: tv = SharpTV(com=com...)

– Feynt
Nov 16 '18 at 13:10






It's technically a serial.Serial() instance (pyserial), but besides in_waiting there's not a lot of difference between a read() on pyserial and a read() on a standard open(). At least not how I'm using it. Changing out the patch, I've got mostly the same code except the following changes: mo = mock_opening(read_data=read_text) with patch('serial.Serial', mo): with serial.Serial() as com: tv = SharpTV(com=com...)

– Feynt
Nov 16 '18 at 13:10














The problem is that you're patching out the builtin open, which may or may not be what you need to be mocking. Why not just patch the com object and be done with it? Furthermore, that function is so simple that it hardly warrants a test...especially if you're going to mock out the write operation...

– Matt Messersmith
Nov 16 '18 at 14:12






The problem is that you're patching out the builtin open, which may or may not be what you need to be mocking. Why not just patch the com object and be done with it? Furthermore, that function is so simple that it hardly warrants a test...especially if you're going to mock out the write operation...

– Matt Messersmith
Nov 16 '18 at 14:12














Digging into dummyserial I found that it's decoding my input back into a string and checking against my dictionary for an actual string versus a byte encoded string. I've adjusted that and it seems like it's working for me now. I have more tests to do beyond this simple sendCmd, but I wanted to make sure I could at least get this working before moving onto (slightly) harder things like testing TV status codes loaded from a config file.

– Feynt
Nov 16 '18 at 14:18






Digging into dummyserial I found that it's decoding my input back into a string and checking against my dictionary for an actual string versus a byte encoded string. I've adjusted that and it seems like it's working for me now. I have more tests to do beyond this simple sendCmd, but I wanted to make sure I could at least get this working before moving onto (slightly) harder things like testing TV status codes loaded from a config file.

– Feynt
Nov 16 '18 at 14:18













1 Answer
1






active

oldest

votes


















0














To answer one part of my question, I figured out the functionality of dummyserial. The following works now:



def testSendCmd(self):
powerCheck = '01:>4r'.format(SharpCodes['POWER'], SharpCodes['CHECK'])
com = dummyserial.Serial(
port='COM1',
baudrate=9600,
ds_responses=powerCheck : powerCheck
)
tv = SharpTV(com=com, TVID=999, tvInput = 'DVI')
tv.sendCmd(SharpCodes['POWER'], SharpCodes['CHECK'])
self.assertEqual(tv.recv(), powerCheck)


Previously I was encoding the dictionary values as utf-8. The dummyserial library decodes whatever you write(...) to it so it's a straight string vs. string comparison. It also encodes whatever you're read()ing as latin1 on the way back out.






share|improve this answer






















    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53327415%2fcan-you-use-mock-open-to-simulate-serial-connections%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    To answer one part of my question, I figured out the functionality of dummyserial. The following works now:



    def testSendCmd(self):
    powerCheck = '01:>4r'.format(SharpCodes['POWER'], SharpCodes['CHECK'])
    com = dummyserial.Serial(
    port='COM1',
    baudrate=9600,
    ds_responses=powerCheck : powerCheck
    )
    tv = SharpTV(com=com, TVID=999, tvInput = 'DVI')
    tv.sendCmd(SharpCodes['POWER'], SharpCodes['CHECK'])
    self.assertEqual(tv.recv(), powerCheck)


    Previously I was encoding the dictionary values as utf-8. The dummyserial library decodes whatever you write(...) to it so it's a straight string vs. string comparison. It also encodes whatever you're read()ing as latin1 on the way back out.






    share|improve this answer



























      0














      To answer one part of my question, I figured out the functionality of dummyserial. The following works now:



      def testSendCmd(self):
      powerCheck = '01:>4r'.format(SharpCodes['POWER'], SharpCodes['CHECK'])
      com = dummyserial.Serial(
      port='COM1',
      baudrate=9600,
      ds_responses=powerCheck : powerCheck
      )
      tv = SharpTV(com=com, TVID=999, tvInput = 'DVI')
      tv.sendCmd(SharpCodes['POWER'], SharpCodes['CHECK'])
      self.assertEqual(tv.recv(), powerCheck)


      Previously I was encoding the dictionary values as utf-8. The dummyserial library decodes whatever you write(...) to it so it's a straight string vs. string comparison. It also encodes whatever you're read()ing as latin1 on the way back out.






      share|improve this answer

























        0












        0








        0







        To answer one part of my question, I figured out the functionality of dummyserial. The following works now:



        def testSendCmd(self):
        powerCheck = '01:>4r'.format(SharpCodes['POWER'], SharpCodes['CHECK'])
        com = dummyserial.Serial(
        port='COM1',
        baudrate=9600,
        ds_responses=powerCheck : powerCheck
        )
        tv = SharpTV(com=com, TVID=999, tvInput = 'DVI')
        tv.sendCmd(SharpCodes['POWER'], SharpCodes['CHECK'])
        self.assertEqual(tv.recv(), powerCheck)


        Previously I was encoding the dictionary values as utf-8. The dummyserial library decodes whatever you write(...) to it so it's a straight string vs. string comparison. It also encodes whatever you're read()ing as latin1 on the way back out.






        share|improve this answer













        To answer one part of my question, I figured out the functionality of dummyserial. The following works now:



        def testSendCmd(self):
        powerCheck = '01:>4r'.format(SharpCodes['POWER'], SharpCodes['CHECK'])
        com = dummyserial.Serial(
        port='COM1',
        baudrate=9600,
        ds_responses=powerCheck : powerCheck
        )
        tv = SharpTV(com=com, TVID=999, tvInput = 'DVI')
        tv.sendCmd(SharpCodes['POWER'], SharpCodes['CHECK'])
        self.assertEqual(tv.recv(), powerCheck)


        Previously I was encoding the dictionary values as utf-8. The dummyserial library decodes whatever you write(...) to it so it's a straight string vs. string comparison. It also encodes whatever you're read()ing as latin1 on the way back out.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 16 '18 at 14:26









        FeyntFeynt

        1316




        1316





























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53327415%2fcan-you-use-mock-open-to-simulate-serial-connections%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            27

            Top Tejano songwriter Luis Silva dead of heart attack at 64

            Category:Rhetoric