Несоответствие в создании дефекта между UI и restApi

Когда я создаю дефект в пользовательском интерфейсе, я не могу назначить его только для тестового примера, пользовательская история назначается автоматически. Если я попытаюсь удалить пользовательскую историю, тестовый пример также исчезнет.

Но через restApi я могу относиться только к Test Case, не упоминая User Story.

Я думаю, что это ошибка, так как поведение должно быть одинаковым независимо от того, как вы создаете Дефект.

Я не упомянул об этом, но у нас всегда есть тестовые случаи, связанные с пользовательскими историями.


person stella    schedule 20.03.2014    source источник


Ответы (1)


Дефект можно связать как с пользовательской историей, так и с тестовым случаем через API и пользовательский интерфейс. Но это происходит в особом случае, когда вы сначала связываете историю с тестовым набором, а затем связываете дефект с этой историей, а затем вы нажимаете поле TestCase на странице сведений о дефекте, и он представляет единственный вариант в средстве выбора. - тестовый случай, уже связанный с историей.

Дальнейшее сбивает с толку.

Существует два способа связать тестовый пример с дефектом в пользовательском интерфейсе Rally:

используя поле «Тестовый пример» на странице «Подробности»

с помощью ссылки «Тестовые примеры» в левой части страницы «Подробности».

Это не только допускает непоследовательность в пользовательском интерфейсе, но и вызывает путаницу, когда пользователи изучают результаты запросов WS API.

Допустим, существующий тестовый пример связан с дефектом с помощью поля «Тестовый пример» на странице сведений о дефекте, а затем новый тестовый пример связан с тем же дефектом с помощью ссылки «Тестовые случаи» на левой стороне.

На данный момент у нас есть два отдельных TestCase, связанных с одним и тем же дефектом: TC7 и TC59.

Однако, когда мы запрашиваем этот дефект и его коллекцию TestCases, он показывает только один TestCase (TC59 в моем примере), который был добавлен по ссылке «Test Cases» слева.

Вот первый запрос, который извлекает коллекцию TestCases:

https://rally1.rallydev.com/slm/webservice/v2.0/defect?workspace=https://rally1.rallydev.com/slm/webservice/v2.0/workspace/1111&query=(FormattedID%20%3D%20DE19)&fetch=TestCases

И результат, возвращаемый первым запросом:

{ 
QueryResult: { 
_rallyAPIMajor: "2", 
_rallyAPIMinor: "0", 
Errors: [ ], 
Warnings: [ ], 
TotalResultCount: 1, 
StartIndex: 1, 
PageSize: 20, 
Results: [ 
{ 
_rallyAPIMajor: "2", 
_rallyAPIMinor: "0", 
_ref: "https://rally1.rallydev.com/slm/webservice/v2.0/defect/12655123753", 
_refObjectUUID: "91f66a35-d860-41e0-a10d-db6dad460f28", 
_objectVersion: "7", 
_refObjectName: "Error found in US20: story C2", 
TestCases: { 
_rallyAPIMajor: "2", 
_rallyAPIMinor: "0", 
_ref: "https://rally1.rallydev.com/slm/webservice/v2.0/Defect/12655123753/TestCases", 
_type: "TestCase", 
Count: 1 
}, 
_type: "Defect" 
} 
] 
} 
}

Используя URI коллекции TestCases, которую мы получили в результате первого запроса, мы запустили другой запрос, чтобы изучить саму коллекцию, для краткости извлекая только FormattedID и WorkProduct:

https://rally1.rallydev.com/slm/webservice/v2.0/Defect/12655123753/TestCases?fetch=FormattedID,WorkProduct 

Результат включает только TC59:

https://rally1.rallydev.com/slm/webservice/v2.0/Defect/12655123753/TestCases?fetch=FormattedID,WorkProduct 

{ 
QueryResult: { 
_rallyAPIMajor: "2", 
_rallyAPIMinor: "0", 
Errors: [ ], 
Warnings: [ ], 
TotalResultCount: 1, 
StartIndex: 1, 
PageSize: 20, 
Results: [ 
{ 
_rallyAPIMajor: "2", 
_rallyAPIMinor: "0", 
_ref: "https://rally1.rallydev.com/slm/webservice/v2.0/testcase/17593081118", 
_refObjectUUID: "dbdbd621-97f7-4c27-b24a-f0ca92be73ff", 
_objectVersion: "1", 
_refObjectName: "Error found in US20: story C2", 
FormattedID: "TC59", 
WorkProduct: { 
_rallyAPIMajor: "2", 
_rallyAPIMinor: "0", 
_ref: "https://rally1.rallydev.com/slm/webservice/v2.0/defect/12655123753", 
_refObjectUUID: "91f66a35-d860-41e0-a10d-db6dad460f28", 
_objectVersion: "7", 
_refObjectName: "Error found in US20: story C2", 
FormattedID: "DE19", 
_type: "Defect" 
}, 
_type: "TestCase" 
} 
] 
} 
} 

Далее мы хотим создать новый TestCase через API веб-сервисов и связать его с тем же Defect DE19. Важно: метод пользовательского интерфейса для связывания нового TestCase с дефектом через ссылку «Test Cases» слева эквивалентен следующему запросу POST в WS API.

В этом примере "WorkProduct":"/defect/12655123753" ссылается на ObjectID того же дефекта.

URL-адрес запроса:

https://rally1.rallydev.com/slm/webservice/v2.0/testcase/create?key=7b193d4b....

Полезная нагрузка:

{ 
"TestCase":{ 
"Name": "some tc", 
"WorkProduct":"/defect/12655123753" 
} 
}

Мы проверяем в пользовательском интерфейсе, что запрос на создание WS API был успешным. Затем мы запрашиваем ту же коллекцию TestCases и видим два результата, как и ожидалось. На этот раз для краткости выбран только FormattedID. TC59 и TC60 возвращаются.

https://rally1.rallydev.com/slm/webservice/v2.0/Defect/12655123753/TestCases?fetch=FormattedID 

Как мы видим, TC7, который был создан в пользовательском интерфейсе через поле «Тестовый пример» на странице сведений о дефекте, не возвращается этим запросом. В объекте Defect API веб-служб есть два атрибута, имеющих отношение к этому обсуждению: TestCase и TestCases.

Этот запрос:

https://rally1.rallydev.com/slm/webservice/v2.0/defect?workspace=https://rally1.rallydev.com/slm/webservice/v2.0/workspace/1111&query=(FormattedID%20%3D%20DE19)&fetch=TestCase,FormattedID

возвращает TC7:

{ 
QueryResult: { 
_rallyAPIMajor: "2", 
_rallyAPIMinor: "0", 
Errors: [ ], 
Warnings: [ ], 
TotalResultCount: 1, 
StartIndex: 1, 
PageSize: 20, 
Results: [ 
{ 
_rallyAPIMajor: "2", 
_rallyAPIMinor: "0", 
_ref: "https://rally1.rallydev.com/slm/webservice/v2.0/defect/12655123753", 
_refObjectUUID: "91f66a35-d860-41e0-a10d-db6dad460f28", 
_objectVersion: "9", 
_refObjectName: "Error found in US20: story C2", 
FormattedID: "DE19", 
TestCase: { 
_rallyAPIMajor: "2", 
_rallyAPIMinor: "0", 
_ref: "https://rally1.rallydev.com/slm/webservice/v2.0/testcase/12476557645", 
_refObjectUUID: "a8d50053-e250-43c1-aebc-58472fec2988", 
_objectVersion: "10", 
_refObjectName: "myTS3", 
FormattedID: "TC7", 
_type: "TestCase" 
}, 
_type: "Defect" 
} 
] 
} 
} 

Теперь, когда мы знаем, как связать TestCase с дефектом в сценарии, когда TestCase добавляется в коллекцию TestCases дефекта как через пользовательский интерфейс, так и через WS API, мы хотим найти эквивалент API для связывания TestCase с дефектом с полем TestCase.

Мы будем использовать дефект, с которым не связана история, поскольку исходный дефект (в моем примере DE19) уже связан с US20. Согласно примечанию к атрибуту TestCase Defect в документации WS API, необходимо указать только один из них.

Примечание Тестовый пример, к которому относится этот дефект. Можно указать либо Requirement, либо TestCase, но не оба одновременно.

Мы собираемся добавить уже существующий TestCase, на который ссылается ObjectID 14604252931, к другому дефекту, DE81, на который ссылается Object ID 14710889543:

URL-адрес запроса:

https://rally1.rallydev.com/slm/webservice/v2.0/defect/14710889543?key=7b193d4b-.... 

Полезная нагрузка:

{"Defect":{ 
"TestCase":"/testcase/14604252931" 
} 
} 

Обратите внимание, что если в этот момент второй дефект DE81 связан со случайной историей в пользовательском интерфейсе, связь с TestCase будет удалена без каких-либо ошибок или предупреждений.

Теперь это становится еще более запутанным. На странице сведений о первом дефекте DE19 мы видим, что с ним связаны как US20, так и TC7. Кажется невозможным связать DE81 с TestCase, используя поле «Test Case» на странице сведений. Когда мы нажимаем на значок увеличительного стекла, диалоговое окно выбора пусто. Оказывается, единственный способ связать DE81 и с UserStory, и с TestCase — это создать новый TestCase, связанный с UserStory.

Эти два шага заключаются в следующем: а. Связать UserStory с TestCase b. Вернитесь к дефекту и щелкните поле «Тестовый пример» на странице сведений. На этот раз диалоговое окно выбора будет заполнено новым TestCase, созданным выше. Теперь с этим Дефектом связаны и TestCase, и UserStory.

Если в этот момент будет предпринята попытка заменить TC61 каким-либо другим TestCase, не связанным с UserStory, она потерпит неудачу. Если эта попытка сделана через API, как показано ниже:

URL-адрес запроса:

https://rally1.rallydev.com/slm/webservice/v2.0/defect/14710889543?key=7b193d4b-.... 

Полезная нагрузка:

{"Defect":{ 
"TestCase":"/testcase/14604252931" 
} 
} 

это приведет к этой ошибке:

{"OperationResult": {"_rallyAPIMajor": "2", "_rallyAPIMinor": "0", "Errors": ["Validation error: Defect.TestCase is an invalid relationship "], "Warnings": []}}

ОБНОВЛЕНИЕ относительно случая, описанного в комментарии Стеллы:

Создал UserStory в UI, назвал его StoryG /userstory/17824476422

Связал с ним новый TestCase через ссылку TestCase в левой части страницы сведений. /тесткейс/17824476889

Теперь этот TestCAse связан с историей через коллекцию TestCases в User Story.

Далее создал дефект через API:

https://rally1.rallydev.com/slm/webservice/v2.0/defect/create?key=733c0893-0e5b-4c66-8204-9a2afa548d36

Полезная нагрузка:

{"Defect":{ 
"Name":"Bug with StoryG",
"Requirement":"/hierarchicalrequirement/17824476422",
"TestCase":"/testcase/17824476889"
}
}

Это работает: новый дефект связан как с UserStory, так и с TestCase. Действительно, это согласуется с пользовательским интерфейсом. При использовании API в полезной нагрузке должны быть указаны как Requirement, так и TestCase. А при создании дефекта в пользовательском интерфейсе нужно указать оба: см. первый абзац ответа. При выборе TestCase средство выбора TestCase отображает только один вариант: TestCase, уже связанный с UserStory.

Ниже приведен сценарий, который не будет работать, который согласуется между API и пользовательским интерфейсом. Посмотрим, что произойдет, если я попытаюсь связать с дефектом несвязанные UserStory и TestCase.

Создал UserStory, StoryH /userstory/17824480704

Связал с ним новый TestCase через ссылку TestCase в левой части страницы сведений. /тесткейс/17824481042

Теперь этот TestCase связан с историей через коллекцию TestCases в User Story.

Затем я ссылаюсь на несвязанный TestCase при создании дефекта: /testcase/17824638756

https://rally1.rallydev.com/slm/webservice/v2.0/defect/create?key=733c0893-0e5b-4c66-8204-9a2afa548d36

Полезная нагрузка:

{"Defect":{ 
"Name":"Bug with StoryH",
"Requirement":"/hierarchicalrequirement/17824480704",
"TestCase":"/testcase/17824638756"
}
}

Это возвращает ошибку, как и ожидалось, и соответствует пользовательскому интерфейсу:

{"CreateResult": {"_rallyAPIMajor": "2", "_rallyAPIMinor": "0", "Errors": ["Validation error: Defect.TestCase is an invalid relationship "], "Warnings": []}}

Есть еще один способ связать все члены этого треугольника дефект-пользовательская история-тестовый пример. Вот где можно наблюдать несоответствие между пользовательским интерфейсом и API:

In UI:

a) свяжите пользовательскую историю с тестовым набором, используя ссылку TestCases слева на странице сведений об истории b) создайте новый дефект, свяжите его с тестовым набором, используя поле Test Case на странице сведений о дефекте.

История автоматически отображается после выбора тестового набора в средстве выбора тестового набора.

в API:

a) связать пользовательскую историю с тестовым случаем, используя ссылку TestCases слева на странице сведений об истории b) создать дефект с помощью REST-клиента браузера, установив его поле TestCase и ожидая, что история будет автоматически связана.

https://rally1.rallydev.com/slm/webservice/v2.0/defect/create?key=5e10c58...

Полезная нагрузка:

{"Defect":{ 
"Name":"Bug with TC77",
"TestCase":"/testcase/17866645137"
}
}

Ссылка Defects(1) слева на странице сведений о тестовом наборе показывает недавно созданный дефект. Однако на странице сведений о Дефекте история не отображается. Я представил ошибку.

Подытожим этот треугольник, как он выглядит в WS API:

  1. Дефект — этот артефакт может иметь ссылку на UserStory через атрибут Requirement и ссылку на TestCase через атрибут TestCase. Согласно документации WSAPI, он может иметь одно или другое, но не оба. При связывании этих трех артефактов все они должны быть согласованы. Если определен дефект, указывающий на Userstory и Testcase, то эти два также должны указывать друг на друга, что фактически является исключением из правила «Или/Или». Атрибут TestCase в дефекте полностью отделен от коллекции TestCases в дефекте.

  2. UserStory — этот артефакт имеет коллекцию TestCases и коллекцию Defect.

  3. TestCase — этот артефакт может иметь указатель на Требование (которое является UserStory) через атрибут WorkProduct.

person nickm    schedule 22.03.2014
comment
Да, это очень запутанно, но я все же считаю, что это ошибка. Вот наш сценарий. У нас есть UserStory US1, с которым связан тестовый пример, назовем его TC1. После выполнения TC1 я хочу зарегистрировать дефект через RestApi и указать, что этот дефект принадлежит TC1, который на самом деле принадлежит US1. Случай 1: я делаю это через пользовательский интерфейс, затем после выбора TC1 автоматически заполняется US1. Если я попытаюсь удалить US1 (отвязать его от этого дефекта), ассоциация TC1 также исчезнет. - person stella; 24.03.2014
comment
Случай 2: я хочу зарегистрировать дефект с помощью RestApi и связать его с TC1, предполагая, что он также сам вызовет связь с US1. Потому что так работает интерфейс. ‹p›Это желаемое для меня поведение. Но Ралли этого не делает. Он связывает дефект ТОЛЬКО с тестовым случаем, поэтому он несовместим с пользовательским интерфейсом и не дает мне правильного количества дефектов, когда я запрашиваю его через User Story. - person stella; 24.03.2014
comment
Я добавил раздел ОБНОВЛЕНИЕ в свой пост выше. Когда я ссылаюсь на поля Requirment и TestCase в полезной нагрузке, оба успешно связаны с дефектом, который создается через WS API, если эти два артефакта уже связаны друг с другом. Если я использую несвязанный TestCase, я получаю ожидаемую ошибку: Defect.TestCase является недопустимым отношением. - person nickm; 25.03.2014
comment
Ник, кажется, я не ясно выразился. Попробую еще раз объяснить. Желаемое поведение от WS API: пока я связываю дефект с тестовым примером, требование (которое является родительским для этого тестового примера) также будет заполнено. Вот как это происходит в пользовательском интерфейсе. Но при использовании WS API этого не происходит. - person stella; 26.03.2014
comment
Стелла, спасибо. Ты прав. Существует много способов создать треугольник пользовательская история-тестовый пример-дефект. Я связывал историю с тестовым набором, а затем создавал дефект, связывая его с историей, и в этом сценарии не было расхождений между пользовательским интерфейсом и API. Но если я связываю историю с тестовым примером, а затем создаю дефект при ссылке на тестовый пример, возникает несоответствие между пользовательским интерфейсом и API. Первый автоматически добавляет ассоциацию с историей, второй — нет. Для достижения трехсторонней связи ссылки TestCase и Requirement должны быть включены в полезную нагрузку при использовании API. - person nickm; 26.03.2014
comment
Спасибо, Ник. Это простой способ получить США на основе номера TC? Похоже, мне придется сделать много тяжелой работы в коде, чтобы достичь желаемого результата. Мы создаем US, затем создаем TC для этого US и затем регистрируем дефект, если Test Case не работает. Вот почему я хотел, чтобы US заполнялся сразу после того, как я запишу дефект и укажу TC - как это происходит в пользовательском интерфейсе. - person stella; 26.03.2014
comment
Объект дефекта имеет атрибут TestCase, который является ссылкой на тестовый пример, с которым он связан. После того, как вы получите ссылку, вы можете получить фактический объект TestCase, который имеет атрибут WorkProduct, который является ссылкой на HierarchicalRequirement (история пользователя). - person nickm; 26.03.2014
comment
Я попробовал WorkProduct, чтобы найти US, связанный с тестовым примером, но он не возвращается. - person stella; 26.03.2014
comment
Должен исправиться, WorkProduct возвращает связанную UserStory, пожалуйста, не обращайте внимания на мой предыдущий комментарий. Спасибо. - person stella; 26.03.2014