julia_v_iluhina

Untitled

Nov 5th, 2016
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 13.93 KB | None | 0 0
  1. В следующий раз - включи в проект и исправленный rest-server.py
  2. и в репозитории - тоже выкладывай
  3. ************************
  4. tasks_default = [
  5.     ...
  6. ]
  7. tasks = copy.deepcopy(tasks_default)
  8. /*
  9.     можно чуть лаконичнее сделать объявление тасок по умолчанию и первоначальное заполнение tasks
  10.  
  11.     import copy - добавь в самом начале, в секции с импортами
  12. */
  13. ***************************
  14. @app.route('/todo/api/v1.0/tasks/reset', methods = ['GET'])
  15. @auth.login_required
  16. def reset_tasks():
  17.     global tasks
  18.     global tasks_2
  19.     tasks = copy.deepcopy(tasks_2)
  20.     return make_response(jsonify( { 'reset is complete': 'OK' } ), 205)
  21.  
  22. или
  23.  
  24. @app.route('/todo/api/v1.0/tasks/reset', methods = ['GET'])
  25. @auth.login_required
  26. def reset_tasks():
  27.     global tasks
  28.     tasks = copy.deepcopy(tasks_default)
  29.     return get_tasks()
  30.  
  31. /*
  32.     мне второй вариант больше нравится
  33.     чуть лаконичнее
  34. */
  35. ***************************************
  36. @app.route('/todo/api/v1.0/tasks', methods = ['POST'])
  37. @auth.login_required
  38. def create_task():
  39.     if not request.json or not 'title' in request.json:
  40.         abort(400)
  41.     task = {
  42.         'id': tasks[-1]['id'] + 1,
  43.         'title': request.json['title'],
  44.         'description': request.json.get('description', ""),
  45.         'done': False
  46.     }
  47.     tasks.append(task)
  48.     return jsonify( { 'task': make_public_task(task) } ), 201
  49. /*
  50.     и вот тут есть проблема)
  51.     если удалить все таски
  52.     и затем - добавлять
  53.     то - вот эта строчка - 'id': tasks[-1]['id'] + 1,
  54.     подведет
  55.  
  56.     https://lancelote.gitbooks.io/intermediate-python/content/book/ternary_operators.html
  57.     https://lancelote.gitbooks.io/intermediate-python/content/book/comprehensions.html (dict абстракции)
  58.     http://www.diveintopython.net/native_data_types/index.html#odbchelper.dict
  59.  
  60. */
  61. ****************************
  62. /*
  63.     лишнего не надо в репозитории хранить
  64. */
  65. ****************************
  66. public class BaseTest {
  67.  
  68.     @Before
  69.     public void resetRestfulBase() {
  70.         resetBase();
  71.     }
  72. }
  73. /*
  74.     я бы не выносила в предка тест-класса ресет
  75.  
  76.     смотри - этот гивен - это часть тест логики
  77.  
  78.     как минимум нельзя называть такой базовый тест-класc как BaseTest
  79.  
  80.     потому что имя ничего не говорит и скрывает "важное"
  81.  
  82.     но более того
  83.     этот гивен на самом деле такой важный, что лучше вообще не скрывать его
  84.     ни в каком базовом классе....
  85.  
  86.     его желательно "видеть" в самом тесте
  87.  
  88.     часто даже не стоит такие вещи в @Before выносить, не смотря на то что код будет не DRY
  89.     но будет еще более явным и очевидным)
  90.  
  91.     Хотя в этом случае наверное с @Before будет таки лучше )
  92.  
  93.     а в классы с именем BaseTest - желательно выносить что-то такое что однозначно общее для всех тестов,
  94.     какие-то настройки может конфигурационные, которые в контексте тест логики смысла не имеют
  95.     и их не грех "скрыть с глаз долой"
  96. */
  97. **************************************************
  98. src/main/java/resourse
  99.  
  100. public class PageResourseRestObject {
  101. /*
  102.     тут по аналогии с пейджами....
  103.     для пейджей - пекедж pages
  104.     для ресурсов - resources
  105.     именно так - в множественном числе
  106.     т к теоретически - пекедж - это контейнер для нескольких ресурсов
  107.  
  108.     Когда на реальном проекте обычно создают класс-ресурс (объект или модуль)
  109.     На реальном проекте обычно создают класс-ресурс (объект или модуль) не сразу, когда начали писать тесты.
  110.     А позже - когда появится необходимость переиспользовать вспомогательные методы в разных тест-классах.
  111.     Или если одни более квалифицированные члены команды разрабатывают класс-ресурс,
  112.     а другие - используют для разработки тестов. Но или если так принято в данной команде)
  113.     Т е - это делается обычно при необходимости. С пейджами - в общем аналогично.
  114.  
  115.     про имя класса PageResourseRestObject
  116.     это не пейдж
  117.     называть класс ...Object - тоже станновато)
  118.  
  119.     Tasks - неплохое имя
  120.     но у нас есть класс Task
  121.     и можно сказать - что мы используем один термин для достаточно разных понятий….
  122.  
  123.     Можно в таком случае для класса-ресурса использовать TasksApi или  TasksRest в таком случае…
  124.  
  125.     Но и Tasks - тоже неплохо…, но хуже)
  126.     Можно пойти на эту уступку в принципе - код понятный, названия наглядные
  127. */
  128.  
  129.     public static final String URI = "http://localhost:5000/todo/api/v1.0/tasks";
  130. /*
  131.     разумно - что вынес в поле ресурса урл рест-сервера
  132.  
  133.     конечно лучше всего, чтобы было где-то еще Сonfiguration.baseUrl в котором именно домен был сохранен
  134.     чтобы его можно было от случая к случаю реконфигурить...
  135.     Ведь это как раз та часть урла - которая не принадлежит ресурсу,
  136.     и зависит от того на каком сервере/по-какому-адресу ресурс/веб-сервис задеплоен
  137.  
  138.     На самом деле здесь есть несколько способов как лучше сделать
  139.  
  140.     Первый, если ты уверен, что тебе не нужно будет одновременно/параллельно посылать запросы на разные урлы
  141.     То тогда можно использовать Configuration.baseUrl - типа обычныя глобальная переменная
  142.  
  143.     если нет, тогда лучше "ооп" подход, когда обьект-ресурс помнит свой базовый урл (доменную часть)
  144.     который передается при создании через конструктор
  145.  
  146.     кстати, придется отказаться от использования  final -
  147.     т к обе части - Configuration.baseUrl и эта переменная -
  148.     теперь настраиваемые будут
  149. */
  150. ******************************************************
  151.     @Test
  152.     public void testUnauthorizedReadTasks() {
  153.         getUnauthorizedResponseAccess();
  154.  
  155.         assertEquals("Unauthorized access", getResponseAnswer());
  156.         assertEquals(403, getResponseStatus());
  157.     }
  158.  
  159.     @Test
  160.     public void testUnauthorizedRead() {
  161.         Response response = requestTo(TasksApi.uri).get();
  162.  
  163.         assertEquals("Unauthorized access", response.readEntity(ErrorContainer.class).getError());
  164.         assertEquals(403, response.getStatus());
  165.     }
  166. /*
  167.     сравни эти варианты
  168.     в общем-то - одно и то же
  169.     но во втором случае - меньше "магии"
  170.     а это лучше
  171.  
  172.     я бы не стала в переменной ресурса - держать ответ
  173.     лучше явно - возвращать ответ
  174. */
  175. **************************************************
  176.     @Test
  177.     public void testReadTasks() {
  178.         getAuthorizedResponceAccess();
  179.  
  180.         assertEquals(200, getResponseStatus());
  181.         assertEquals(2, getTasksSize());
  182.         assertEquals("First task", getTask(0).getTitle());
  183.     }
  184.  
  185.     @Test
  186.     public void testRead() {
  187.         List<Task> actualTasks = TasksApi.get();
  188.  
  189.         assertEquals(Arrays.asList(DEFAULT_TASKS), actualTasks);
  190.     }
  191. /*
  192.     можем вот такой код получить
  193.         если
  194.             внутри методов класса-ресурса - проверять статус ответа
  195.  
  196.             Правильный статус ответа на каждый из запросов - строго определенный
  197.                 И если мы будем проверять статут ответа в тест-методе -
  198.                 то надо об этом думать и вспоминать - какой статус в каких случаях верный
  199.                 И можно выкрутиться - проверять статус ответа внутри степа,
  200.                 а возвращать собственно entity из запроса.
  201.                 Сразу пара потенциально полезных моментов)
  202.  
  203.             Если встроить проверку response кода прямо в сам степ
  204.             Тут сразу появляется интересный нюанс
  205.             Дело в том, что мы так спрячем тестовую логику внутрь степа, что не очень хорошо
  206.             С другой стороны - эта проверка = само собой разумеющееся
  207.             Эта проверка достаточно стандартная и всегда будет повторяться после вызова степа
  208.             (если будет жить вне степа)
  209.             А раз так - то почему бы и не спрятать?
  210.             На самом деле - нет однозначного ответа на этот вопрос...
  211.             Так - со спрятанной проверкой - код станет проще во всех тестах -
  212.             но втанет до некоторой степени “магическим”
  213.             Тут надо решать самостоятельно - как лучше )
  214.             На твое усмотрение
  215.  
  216.             Еще момент
  217.             В этих API тестах - самих тестов может быть не так уж и много -
  218.             чтоб еще и заморачиваться над DRY кода...нужно и этот аспект учитывать
  219.  
  220.             Но если пойти этим путем = прятать в степе проверку статуса response,
  221.             то код будет намного более удобным
  222.  
  223.     а чтобы можно было вот так сравнивать
  224.     assertEquals(Arrays.asList(DEFAULT_TASKS), actualTasks)
  225.         посмотри на информацию по этим линкам
  226.         http://www.java2s.com/Tutorial/Java/0140__Collections/CheckingforEquality.htm
  227.         http://www.javapractices.com/topic/TopicAction.do?Id=17
  228.         http://javadevnotes.com/java-array-to-list-examples
  229.         А если реализуешь метод toString для класса Task - и сообщение об ошибке будет более информативным.
  230.  
  231.     так сравнение будет гораздо точнее
  232.         ты сверяешь лишь размер и заголовок одной из тасок
  233.         я предлагаю - сверить весь список тасок (все свойства каждой таски)
  234.  
  235.     для этого - нам таски по умолчанию (таски после ресета) - надо описать в DEFAULT_TASKS
  236. */
  237.  
  238. /*
  239.     Вообще - с вынесением тестовых данных в переменные надо быть осторожным
  240.     Важно - не надо тестовые данные объявлять в ресурс модуле
  241.     (опять аналогия с пейджом - мы и там такого правила придерживались)
  242.  
  243.     Тут и правда есть смысл объявить эти данные
  244.     Часто тестовые данные разумно оставлять в логике самих тестов -
  245.     таким образом код тестов более очевидный. Пример - тудуэмвиси тесты
  246. */
  247. ***************************************************
  248. public void testCreateTask() {
  249. /*
  250.     Кстати, есть смысл создавать таску не только с title,
  251.     но и с description и другими параметрами, чтобы полнее проверить создание таски
  252.     Стоит реализовать два вариантов теста - только с title и по полной информации о таске
  253. */
  254. /*
  255.     пока остановилась)
  256.     полного разбора не сделала
  257.     пока это поправь)
  258. */
Advertisement
Add Comment
Please, Sign In to add comment