@Jungles
Молодой и зелёный

Как работает Unittest?

код программы
spoiler
import requests


class Asteroid():
    BASE_API_URL = 'http://www.neowsapp.com/rest/v1/neo/{}?api_key=DEMO_KEY'

    def __init__(self,spk_id):
        self.api_url = self.BASE_API_URL.format(spk_id)

    def get_data(self):
        return requests.get(self.api_url).json()

    @property
    def name(self):
        return self.get_data()['name']

    @property
    def diameter(self):
        return float(self.get_data()['estimated_diameter']['meters']['estimated\
_diameter_max'])


код теста
spoiler
import json
import unittest
from unittest.mock import patch

from asteroid import Asteroid


class TestAsteroid(unittest.TestCase):

    def setUp(self):
        self.asteroid = Asteroid(3726710)
    #в случае, если интернета нет, возвращаются данные из текстового файла, с тем же содержимым, которое возвращает API
    
    def mocked_get_data(self):
        with open('asteroid_info.txt', 'r') as f:
            return json.loads(f.read())
        

    @patch('asteroid.Asteroid.get_data' , mocked_get_data)
    def test_name(self):
        self.assertEqual(
            self.asteroid.name, '(2015 RC)')

    @patch('asteroid.Asteroid.get_data' , mocked_get_data)
    def test_diameter(self):
        self.assertEqual(self.asteroid.diameter, 82.0427064882)
    

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


Вопрос по методу после комментария.
каким образом данные из файла передаеются self.name и self.diameter?
предполагаю, что тут
@patch('asteroid.Asteroid.get_data' , mocked_get_data)

Но интересно, как это реализовано

То есть если бы метода не было.
Мы бы ловили ошибку, 1) о разрыве HTTP запроса, и следовательно отсутствия self.name и self.diameter

Но как-то мы переключаемся на данные из файла и читаем уже оттуда. Но как это происходит?
может как-то меняется значения ,допустим,
def mocked_get_data(self):
        with open('asteroid_info.txt', 'r') as f:
            data =  json.loads(f.read())
            # неявно self.asteroid.name = data['name']

или как-то по-другому?

ЗЫ: блиц-вопрос.

Почему
a = Asteroid(32241432)
Выполняется спокойно, а вот
a.name выводи список из ConnectionError ,
1) почему при a = Asteroid(32241432) не вызвалась эта ошибка
2) почему при a.name не вызвалась ошибка NameError
  • Вопрос задан
  • 47 просмотров
Решения вопроса 1
fox_12
@fox_12 Куратор тега Python
Расставляю биты, управляю заряженными частицами
@patch('asteroid.Asteroid.get_data' , mocked_get_data)

В тесте метод get_data класса Asteroid модуля asteroid подменяется выводом функции mocked_get_data, которая просто выводит содержимое файла asteroid_info.txt, имитируя запрос внешнего АПИ
Если бы этого патча не было - то дергался бы реальный АПИ

Почему
a = Asteroid(32241432)
Выполняется спокойно

потому что происходит обыкновенное присваивание
def __init__(self,spk_id):
        self.api_url = self.BASE_API_URL.format(spk_id)


а вот a.name выводи список из ConnectionError ,

Потому что при вызове name вызывается requests.get(self.api_url), который дергает внешний апи. И если тот не отвечает - выводит ConnectionError
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы