简体   繁体   中英

How to approach this unit-testing issue based on an external class?

I have a class Node ( add_node.py ) in which I create nodes that connect to a websocket. Now I want to write unit-tests for checking whether or not the connection was successful, and for checking the response of the server.

So I created a node_tests.py file which the following content:

import unittest
import json
import re
from add_node import Node

class TestNodes(unittest.TestCase):

    def test_node_creation(self):
        self.node = Node(a='1', b='2', c=True)
        self.response = json.loads(self.node.connect())
        self.assertIn('ok', self.response['r'])

    def test_node_c(self):
        self.assertTrue(self.response['c'])

if __name__ == '__main__':
    unittest.main()

The first method is working but the second is failing because there is no attribute 'response'. So how could I approach this problem?

Also, is it ok to do it they way I'm doing it? Importing the class and writing multiple test within the same Test class?

The point of a unit test is to verify the functionality of a single isolated unit. Exactly what a unit is can be debated. Some would argue it's a single public method on a single class. I think most would agree that is not a very useful definition though. I like to think of them as use-cases. Your tests should do one use-case, and then make one assertion about the results from that use-case. This means that sometimes it's OK to let classes collaborate, and sometimes it's better to isolate a class and use test doubles for it's dependencies.

Knowing when to isolate is something you learn over time. I think the most important points to consider are that every test you write should

  • Fully define the context in which it's run (without depending on global state or previously run tests)

  • Be fast, a few milliseconds tops (this means you don't touch external resources like the file system, a web server or some database)

  • Not test a bunch of other things that are covered by other tests.

This third point is probably the hardest to balance. Obviously several tests will run the same code if they're making different assertions on the same use-case. You should keep the tests small though. Let's say we want to test the cancellation process of orders in an e-commerce application. In this case we probably don't want to import and set up all the classes used to create, verify, etc. an order before we cancel it. In that case it's probably a better idea to just create an order object manually or maybe use a test double.

In your case, if what you actually want to do is to test the real connection and the responses the real server gives, you don't want a unit test, you want an integration test.

If what you actually want is to test the business logic of your client class, however, you should probably create a fake socket/server where you can yourself define the responses and whether or not the connection is successful. This allows you to test that your client behaves correctly depending on it's communications with the remote server, without actually having to depend on the remote server in your test suite.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM