Computing a list from Graphite JSON I had a simple function.

def graphite_json(target):
    url = 'http://server/render/?format=json&amp;amp;target={}&amp;amp;from=-10days'.format(target)
    r = requests.get(url)
    return r.json()


This contacts  a (Graphite) server, uses the requests library to get JSON string and convert it to a native list. Simple.

Then I wanted to test it and made a complete mess. My thinking was: I'll soon need more Graphite functionality so best to create a class, also have the requests library as an external dependency so that I can test better. What I ended up with is this:

The Business Logic:

import json
import requests

class Graphite(object):

    def __init__(self, server_url = 'http://server', requests_module=requests):
        self.requests = requests_module
        self.server_url = server_url

    def get(self, metric):

        url = '{}/render/?format=json&amp;amp;target={}'.format(
            self.server_url, metric)
        response = self.requests.get(url)
        return response.json()


The Test

import json
import os
import pytest
from api.graphite import Graphite

@pytest.fixture(scope="session")
def sample_response():
    dirpath = os.path.dirname(os.path.realpath(__file__))
    with open('{}/data/graphite_response.json'.format(dirpath), 'r') as content_file:
        content = content_file.read()
    return content

@pytest.fixture(scope="session")
def mock_graphite_requests(sample_response):
    class Requests(object):
        def get(self, url):
            if 'target' not in url:
                raise NotImplementedError('need a target for graphite stats')
            class Response(object):
                def __init__(self, data):
                    self.data = data
                def json(self):
                    return json.loads(self.data)
            return Response(sample_response)
    return Requests()

@pytest.fixture(scope="session")
def graphite(mock_graphite_requests):
    return Graphite(requests_module=mock_graphite_requests)

def test_graphite_metric(graphite, sample_response):
    data = graphite.get('summarize(stats.gauges.items,"12hour","avg")')
    assert data == json.loads(sample_response)


I see this as weak because:


The test is huge! I'll have to maintain it, probably.
What am I actually testing? I think I only test that this class converts the response from JSON.


How can I fix this mess?
You don't want to test the network, the requests or json libraries, you want to check that your method calls requests with a certain parameter (to check if your string interpolation worked and used the correct arguments) and that you return the return value of the JSON method of the response (to check whether you actually used and passed through the object).

At least those are things worthy of testing.  You can simplify your code with mocks if you like them, otherwise I'd say move the class definitions so that you have proper MockRequests and MockResponse classes, maybe the requests with a response constructor argument or so.

And the classes should be as simple as possible, the check for "target" isn't necessary, just check whether the incoming URL has the correct (pre-set) value.  The response shouldn't call anything, it should just return the (again pre-set) JSON object instead.