简体   繁体   中英

py.test: Mocking a datetime object that is constantly changing

How do you mock a returned datetime object if that object is constantly changing?

For example I have some code that queries an api, gets some timeseries data and returns it as a series of datetime objects.

So the return data from the queried api looks something like:

{
    'from_date': 1497881400000.0,
                'group_by': [],
                'message': '',
                'query': 'avg:system.load.norm.5{role:lb}',
                'res_type': 'time_series',
                'resp_version': 1,
                'series': [{'aggr': 'avg',
                                    'attributes': {},
                                    'display_name': 'system.load.norm.5',
                                    'end': 1497709799000,
                                    'expression': 'avg:system.load.norm.5{role:lb}',
                                    'interval': 1,
                                    'length': 60,
                                    'metric': 
                                    'avg:system.load.norm.5{role:lb}',
                                    'pointlist': [[1497881400000.0,
                                     0.06923198629355053], 
                                    [.. 60 more points]],
                                    'query_index': 0,
                                    'scope': 'role:lb',
                                    'start': 1497709742000,
                                    'unit': [None, None]}],
                'status': 'ok',
                'to_date': 1497709800000
}

and my code does this:

from typing import NamedTuple

class SampleMetric(NamedTuple):
    query: str
    time: datetime.datetime
    value: int

pointlist = api_query['series'][0]['pointlist']
return [SampleMetric(query=metric,
                             time=datetime.datetime.fromtimestamp(
                                 point[0] / 1000),
                             value=point[1]) for point in pointlist]

which in the case of the above api data would look something like this:

[SampleMetric(query='avg:system.load.norm.5{role:lb}', time=datetime.datetime(2017, 10, 20, 11, 2), value=231.8605833053589),
 SampleMetric(query='avg:system.load.norm.5{role:lb}', time=datetime.datetime(2017, 10, 20, 11, 3), value=243.17432022094727),...]

So I can easily create a mock api object that returns a dictionary as our example does above, but I'm really struggling to mock the changing datetime object that's returned.

ie time=datetime.datetime(2017, 10, 20, 11, 2)

Can anyone give me any ideas on how to do this please? At the moment I've got around this by only having one timeseries point in my return data and hardcoding the time value, but I feel this isn't really a real world test as it should return 60 results.

PLEASE ignore the actual values used in this example, I know they're wrong but this is just for illustration purposes as I'm struggling to explain what I mean.

I'm not sure exactly what you mean by "constantly changing", so I'm going to take two guesses and answer both of them.

My first guess is that you're wondering how to write a unit test when the results depend on the current time. That makes the outputs constantly change, so the test is hard to write.

To solve that problem, I either pass the current time as an explicit input parameter to the code I'm testing, or I mock the datetime.now() method. That way, the unit test always calculates based on the same time, and should always get the same result. That also makes it much easier to test interesting edge cases, like the change in daylight saving. You can write a separate test case for each interesting scenario with a different "current time" in each.

My second guess is that you're asking how to create a set of 60 different datetime values for your input data. I would probably calculate a couple of interesting values for the first few entries, and then just generate the rest with a for loop or a range() expression.

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