Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
От Зефира в коробке к
Structure Zephyr
или
Как тест-менеджеру
перекроить внутренности JIRA
Никита Налютин
Experian
Предупреждение
В презентации есть
быдлокод (с багами) грязные трюки
и
Код здесь: https://github.com/p1ne/jira-zephyr-plus-...
О чем будем говорить
• Что такое Zephyr и Structure
• Зачем дружить Zephyr и Structure
• Как влезть в JIRA скриптами
• Как...
Structure – как все красиво организовать
marketplace.atlassian.com/plugins/com.almworks.jira.structure
Zephyr - как выглядят тесты
marketplace.atlassian.com/plugins/com.thed.zephyr.je
Хотим вот такой вид тестов
Хотим вот такую отчетность
Проблема
• Тест и прогон теста – разные сущности
• Статусы тестов – поля прогона теста, а не теста
• Нужен механизм пробро...
Скриптовые поля: Adaptivist Script Runner
marketplace.atlassian.com/plugins/com.onresolve.jira.groovy.groovyrunner/
Вариант реализации: ZAPI
"http://jira/rest/zapi/latest/execution?issueId=" + issueID
URLConnection urlConnection = url.ope...
Как увидеть таблицы плагинов
Как попробовать извлечь данные
marketplace/plugins/info.renjithv.jira.plugins.sysadmin.homedirectorybrowser
Вариант реализации: из базы
def delegator =
ComponentAccessor.getComponent(DelegatorInterface)
String helperName = delegat...
Как выбрать данные в скрипте
sqlStmt = "SELECT issue_id FROM ao_7deabf_schedule
where project_id = " + projectId + " and
(...
Почему данные неактуальны?
• У Zephyr нет событий, означающих обновление test run
• JIRA кеширует значения атрибутов
• Пои...
Реиндекс и поиск: правильно,
но не работает
• Проблема: При попытке искать по кастом полям ничего не
находится или находит...
Реиндекс: правильно,
но ооооочень долго
Пинаем реиндекс:
почти работает
def issueIndexManager =
ComponentAccessor.getIssueIndexManager();
def events = ComponentAc...
Запуск реиндекса
• com.onresolve.jira.groovy.GroovyService – не заработало
• NSSM и периодический запуск ScriptRunner чере...
А еще хотим выполнять тесты…
SELECT s.status, v.vname, s.id
FROM ao_7deabf_schedule s, projectversion v
WHERE s.project_id...
А еще хотим выполнять тесты…
if (!versionName.equals("") &&
(statusName.equals("UNEXECUTED") ||
statusName.equals("IN PROG...
А еще хотим выполнять тесты…
if (versionName.equals("")
<a id="zephyr-je-add-execute"
title="Execute Test"
class="toolbar-...
Что делать с форматированием и поиском
coloredStatus = ”
<div class="labels exec-status-container">
<dd style="background-...
А еще хотим быстро планировать
А еще хотим экспорт тест-плана в документ
• Поле Preview, которое начинается с </td>
retStr += "</td></tr><tr style="width...
А еще хотим экспорт тест-плана в документ
Вопросы?
Код здесь: https://github.com/p1ne/jira-zephyr-plus-structure/
Upcoming SlideShare
Loading in …5
×

От Зефира в коробке к Structure Zephyr или как тест-менеджеру перекроить внутренности JIRA

594 views

Published on

Доклад Никиты Налютина на SQA Days-22. 17-18 ноября 2017. Санкт-Петербург, Россия
www.sqadays.com

Published in: Education
  • Be the first to comment

  • Be the first to like this

От Зефира в коробке к Structure Zephyr или как тест-менеджеру перекроить внутренности JIRA

  1. 1. От Зефира в коробке к Structure Zephyr или Как тест-менеджеру перекроить внутренности JIRA Никита Налютин Experian
  2. 2. Предупреждение В презентации есть быдлокод (с багами) грязные трюки и Код здесь: https://github.com/p1ne/jira-zephyr-plus-structure/
  3. 3. О чем будем говорить • Что такое Zephyr и Structure • Зачем дружить Zephyr и Structure • Как влезть в JIRA скриптами • Как влезть в БД JIRA • Как влезть в форматирование страниц • Как этим всем сделать всем хорошо • Как этого не делать • …и о муми-троллях…
  4. 4. Structure – как все красиво организовать marketplace.atlassian.com/plugins/com.almworks.jira.structure
  5. 5. Zephyr - как выглядят тесты marketplace.atlassian.com/plugins/com.thed.zephyr.je
  6. 6. Хотим вот такой вид тестов
  7. 7. Хотим вот такую отчетность
  8. 8. Проблема • Тест и прогон теста – разные сущности • Статусы тестов – поля прогона теста, а не теста • Нужен механизм проброса статуса теста на уровень теста • Статус теста может быть разным в разных версиях/прогонах • Выход – поля • Latest test status • Latest test execution
  9. 9. Скриптовые поля: Adaptivist Script Runner marketplace.atlassian.com/plugins/com.onresolve.jira.groovy.groovyrunner/
  10. 10. Вариант реализации: ZAPI "http://jira/rest/zapi/latest/execution?issueId=" + issueID URLConnection urlConnection = url.openConnection(); … BufferedReader reader = new BufferedReader( new InputStreamReader(urlConnection.getInputStream())); StringBuffer response = new StringBuffer(); … def slurper = new JsonSlurper() def result = slurper.parseText(response.toString()) if (result.recordsCount.toInteger() > 0) return result.executions[0].versionName; marketplace.atlassian.com/plugins/com.thed.zephyr.zapi/
  11. 11. Как увидеть таблицы плагинов
  12. 12. Как попробовать извлечь данные marketplace/plugins/info.renjithv.jira.plugins.sysadmin.homedirectorybrowser
  13. 13. Вариант реализации: из базы def delegator = ComponentAccessor.getComponent(DelegatorInterface) String helperName = delegator.getGroupHelperName("default"); StringBuffer sb = new StringBuffer() def sqlStmt = ”..."; Connection conn = ConnectionFactory.getConnection(helperName); Sql sql = new Sql(conn) sql.eachRow(sqlStmt) { sb << "${it.status}” def statusName = status[sb.toString()][0] }
  14. 14. Как выбрать данные в скрипте sqlStmt = "SELECT issue_id FROM ao_7deabf_schedule where project_id = " + projectId + " and (date_created between '" + timestamp.format(10.minutes.ago) + "' and '" + timestamp.format(0.minutes.from.now) + "' or executed_on between '" + (unixTime - 10*60*1000).toString() + "' and '" + unixTime.toString() + "') order by date_created desc";
  15. 15. Почему данные неактуальны? • У Zephyr нет событий, означающих обновление test run • JIRA кеширует значения атрибутов • Поиск JQL работает исходя из кэша • Частичное обновление кэша работает на весь проект • Решение – периодическая перестройка кэша
  16. 16. Реиндекс и поиск: правильно, но не работает • Проблема: При попытке искать по кастом полям ничего не находится или находится не все или не сразу • Решение: само пройдет. • Не проходит • Решение: enableCache = {-> false} • Не дает искать в принципе
  17. 17. Реиндекс: правильно, но ооооочень долго
  18. 18. Пинаем реиндекс: почти работает def issueIndexManager = ComponentAccessor.getIssueIndexManager(); def events = ComponentAccessor.getIssueEventManager(); sql.eachRow(sqlStmt) { def issue = ComponentAccessor.getIssueManager().getIssueObject(it.issue_i d.toLong()); issueIndexManager.reIndex(issue); events.dispatchEvent(EventType.ISSUE_UPDATED_ID, issue, user, false); }
  19. 19. Запуск реиндекса • com.onresolve.jira.groovy.GroovyService – не заработало • NSSM и периодический запуск ScriptRunner через POST curl "http://jira/rest/scriptrunner/latest/user/exec/" ^ -H "Host: jira" ^ -H "Accept: application/json, text/javascript, */*; q=0.01" ^ -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" ^ -H "X-Atlassian-Token: nocheck" ^ -H "X-Requested-With: XMLHttpRequest" ^ -H "Referer: http://jira/plugins/servlet/scriptrunner/console?section=script_console" ^ --data "scriptText=&scriptFile=reindex.groovy&htmlText=&jsText=" https://nssm.cc/ https://curl.haxx.se/
  20. 20. А еще хотим выполнять тесты… SELECT s.status, v.vname, s.id FROM ao_7deabf_schedule s, projectversion v WHERE s.project_id=" + projectId + " and s.issue_id=" + issueId + " and s.version_id = v.id order by s.date_created desc limit 1";
  21. 21. А еще хотим выполнять тесты… if (!versionName.equals("") && (statusName.equals("UNEXECUTED") || statusName.equals("IN PROGRESS")) ) … <a href="/secure/enav/#/" + executionId + ""> <span class="trigger-label">Continue exec </span> </a>
  22. 22. А еще хотим выполнять тесты… if (versionName.equals("") <a id="zephyr-je-add-execute" title="Execute Test" class="toolbar-trigger viewissue-add-execute” href="/secure/AddExecute!AddExecute.jspa?id=" + issueId + ""> <span class="trigger-label">Exec new </span> </a>
  23. 23. Что делать с форматированием и поиском coloredStatus = ” <div class="labels exec-status-container"> <dd style="background-color: " + statusColor + "">” + statusName + "</dd></div>"; status = statusName
  24. 24. А еще хотим быстро планировать
  25. 25. А еще хотим экспорт тест-плана в документ • Поле Preview, которое начинается с </td> retStr += "</td></tr><tr style="width: 100%;"> <td colspan="10" style="font-size: 10pt;">” retStr += wikiRenderer.render(issue.getDescription(), null) retStr += "<br/>"
  26. 26. А еще хотим экспорт тест-плана в документ
  27. 27. Вопросы? Код здесь: https://github.com/p1ne/jira-zephyr-plus-structure/

×