Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- В следующий раз - включи в проект и исправленный rest-server.py
- и в репозитории - тоже выкладывай
- ************************
- tasks_default = [
- ...
- ]
- tasks = copy.deepcopy(tasks_default)
- /*
- можно чуть лаконичнее сделать объявление тасок по умолчанию и первоначальное заполнение tasks
- import copy - добавь в самом начале, в секции с импортами
- */
- ***************************
- @app.route('/todo/api/v1.0/tasks/reset', methods = ['GET'])
- @auth.login_required
- def reset_tasks():
- global tasks
- global tasks_2
- tasks = copy.deepcopy(tasks_2)
- return make_response(jsonify( { 'reset is complete': 'OK' } ), 205)
- или
- @app.route('/todo/api/v1.0/tasks/reset', methods = ['GET'])
- @auth.login_required
- def reset_tasks():
- global tasks
- tasks = copy.deepcopy(tasks_default)
- return get_tasks()
- /*
- мне второй вариант больше нравится
- чуть лаконичнее
- */
- ***************************************
- @app.route('/todo/api/v1.0/tasks', methods = ['POST'])
- @auth.login_required
- def create_task():
- if not request.json or not 'title' in request.json:
- abort(400)
- task = {
- 'id': tasks[-1]['id'] + 1,
- 'title': request.json['title'],
- 'description': request.json.get('description', ""),
- 'done': False
- }
- tasks.append(task)
- return jsonify( { 'task': make_public_task(task) } ), 201
- /*
- и вот тут есть проблема)
- если удалить все таски
- и затем - добавлять
- то - вот эта строчка - 'id': tasks[-1]['id'] + 1,
- подведет
- https://lancelote.gitbooks.io/intermediate-python/content/book/ternary_operators.html
- https://lancelote.gitbooks.io/intermediate-python/content/book/comprehensions.html (dict абстракции)
- http://www.diveintopython.net/native_data_types/index.html#odbchelper.dict
- */
- ****************************
- /*
- лишнего не надо в репозитории хранить
- */
- ****************************
- public class BaseTest {
- @Before
- public void resetRestfulBase() {
- resetBase();
- }
- }
- /*
- я бы не выносила в предка тест-класса ресет
- смотри - этот гивен - это часть тест логики
- как минимум нельзя называть такой базовый тест-класc как BaseTest
- потому что имя ничего не говорит и скрывает "важное"
- но более того
- этот гивен на самом деле такой важный, что лучше вообще не скрывать его
- ни в каком базовом классе....
- его желательно "видеть" в самом тесте
- часто даже не стоит такие вещи в @Before выносить, не смотря на то что код будет не DRY
- но будет еще более явным и очевидным)
- Хотя в этом случае наверное с @Before будет таки лучше )
- а в классы с именем BaseTest - желательно выносить что-то такое что однозначно общее для всех тестов,
- какие-то настройки может конфигурационные, которые в контексте тест логики смысла не имеют
- и их не грех "скрыть с глаз долой"
- */
- **************************************************
- src/main/java/resourse
- public class PageResourseRestObject {
- /*
- тут по аналогии с пейджами....
- для пейджей - пекедж pages
- для ресурсов - resources
- именно так - в множественном числе
- т к теоретически - пекедж - это контейнер для нескольких ресурсов
- Когда на реальном проекте обычно создают класс-ресурс (объект или модуль)
- На реальном проекте обычно создают класс-ресурс (объект или модуль) не сразу, когда начали писать тесты.
- А позже - когда появится необходимость переиспользовать вспомогательные методы в разных тест-классах.
- Или если одни более квалифицированные члены команды разрабатывают класс-ресурс,
- а другие - используют для разработки тестов. Но или если так принято в данной команде)
- Т е - это делается обычно при необходимости. С пейджами - в общем аналогично.
- про имя класса PageResourseRestObject
- это не пейдж
- называть класс ...Object - тоже станновато)
- Tasks - неплохое имя
- но у нас есть класс Task
- и можно сказать - что мы используем один термин для достаточно разных понятий….
- Можно в таком случае для класса-ресурса использовать TasksApi или TasksRest в таком случае…
- Но и Tasks - тоже неплохо…, но хуже)
- Можно пойти на эту уступку в принципе - код понятный, названия наглядные
- */
- public static final String URI = "http://localhost:5000/todo/api/v1.0/tasks";
- /*
- разумно - что вынес в поле ресурса урл рест-сервера
- конечно лучше всего, чтобы было где-то еще Сonfiguration.baseUrl в котором именно домен был сохранен
- чтобы его можно было от случая к случаю реконфигурить...
- Ведь это как раз та часть урла - которая не принадлежит ресурсу,
- и зависит от того на каком сервере/по-какому-адресу ресурс/веб-сервис задеплоен
- На самом деле здесь есть несколько способов как лучше сделать
- Первый, если ты уверен, что тебе не нужно будет одновременно/параллельно посылать запросы на разные урлы
- То тогда можно использовать Configuration.baseUrl - типа обычныя глобальная переменная
- если нет, тогда лучше "ооп" подход, когда обьект-ресурс помнит свой базовый урл (доменную часть)
- который передается при создании через конструктор
- кстати, придется отказаться от использования final -
- т к обе части - Configuration.baseUrl и эта переменная -
- теперь настраиваемые будут
- */
- ******************************************************
- @Test
- public void testUnauthorizedReadTasks() {
- getUnauthorizedResponseAccess();
- assertEquals("Unauthorized access", getResponseAnswer());
- assertEquals(403, getResponseStatus());
- }
- @Test
- public void testUnauthorizedRead() {
- Response response = requestTo(TasksApi.uri).get();
- assertEquals("Unauthorized access", response.readEntity(ErrorContainer.class).getError());
- assertEquals(403, response.getStatus());
- }
- /*
- сравни эти варианты
- в общем-то - одно и то же
- но во втором случае - меньше "магии"
- а это лучше
- я бы не стала в переменной ресурса - держать ответ
- лучше явно - возвращать ответ
- */
- **************************************************
- @Test
- public void testReadTasks() {
- getAuthorizedResponceAccess();
- assertEquals(200, getResponseStatus());
- assertEquals(2, getTasksSize());
- assertEquals("First task", getTask(0).getTitle());
- }
- @Test
- public void testRead() {
- List<Task> actualTasks = TasksApi.get();
- assertEquals(Arrays.asList(DEFAULT_TASKS), actualTasks);
- }
- /*
- можем вот такой код получить
- если
- внутри методов класса-ресурса - проверять статус ответа
- Правильный статус ответа на каждый из запросов - строго определенный
- И если мы будем проверять статут ответа в тест-методе -
- то надо об этом думать и вспоминать - какой статус в каких случаях верный
- И можно выкрутиться - проверять статус ответа внутри степа,
- а возвращать собственно entity из запроса.
- Сразу пара потенциально полезных моментов)
- Если встроить проверку response кода прямо в сам степ
- Тут сразу появляется интересный нюанс
- Дело в том, что мы так спрячем тестовую логику внутрь степа, что не очень хорошо
- С другой стороны - эта проверка = само собой разумеющееся
- Эта проверка достаточно стандартная и всегда будет повторяться после вызова степа
- (если будет жить вне степа)
- А раз так - то почему бы и не спрятать?
- На самом деле - нет однозначного ответа на этот вопрос...
- Так - со спрятанной проверкой - код станет проще во всех тестах -
- но втанет до некоторой степени “магическим”
- Тут надо решать самостоятельно - как лучше )
- На твое усмотрение
- Еще момент
- В этих API тестах - самих тестов может быть не так уж и много -
- чтоб еще и заморачиваться над DRY кода...нужно и этот аспект учитывать
- Но если пойти этим путем = прятать в степе проверку статуса response,
- то код будет намного более удобным
- а чтобы можно было вот так сравнивать
- assertEquals(Arrays.asList(DEFAULT_TASKS), actualTasks)
- посмотри на информацию по этим линкам
- http://www.java2s.com/Tutorial/Java/0140__Collections/CheckingforEquality.htm
- http://www.javapractices.com/topic/TopicAction.do?Id=17
- http://javadevnotes.com/java-array-to-list-examples
- А если реализуешь метод toString для класса Task - и сообщение об ошибке будет более информативным.
- так сравнение будет гораздо точнее
- ты сверяешь лишь размер и заголовок одной из тасок
- я предлагаю - сверить весь список тасок (все свойства каждой таски)
- для этого - нам таски по умолчанию (таски после ресета) - надо описать в DEFAULT_TASKS
- */
- /*
- Вообще - с вынесением тестовых данных в переменные надо быть осторожным
- Важно - не надо тестовые данные объявлять в ресурс модуле
- (опять аналогия с пейджом - мы и там такого правила придерживались)
- Тут и правда есть смысл объявить эти данные
- Часто тестовые данные разумно оставлять в логике самих тестов -
- таким образом код тестов более очевидный. Пример - тудуэмвиси тесты
- */
- ***************************************************
- public void testCreateTask() {
- /*
- Кстати, есть смысл создавать таску не только с title,
- но и с description и другими параметрами, чтобы полнее проверить создание таски
- Стоит реализовать два вариантов теста - только с title и по полной информации о таске
- */
- /*
- пока остановилась)
- полного разбора не сделала
- пока это поправь)
- */
Advertisement
Add Comment
Please, Sign In to add comment