Я опубликую то, что сделал, чтобы результаты теста SpecFlow отображались в области Azure DevOps Builds-> Tests, однако предупреждаю, что это хак гигант .
Я полагаю, что тесты SpecFlow / NUnit предполагается поддерживаются так же, как и обычные тесты NUnit, и я думаю, что это связано с настройкой тестового адаптера, как заявил Андреас Виллих, однако я так и не смог его получить работать на меня, и я не смог найти примеры того, где кто-то заставил это работать через обычную конфигурацию конвейера. SpecFlow + также может иметь способы работы, но я не использую версию «плюс». Если / когда я смогу узнать, как это сделать, я перестану использовать нижеприведенное.
Создайте простой процесс для записи имени теста SpecFlow и значений результата теста на диск в формате CSV. Я сделал это, потому что хотел отделить решения по тестированию функций от любой другой логики, применяемой в этом хакере. Этот процесс должен быть таким же простым, как использование шага ловушки [AfterScenario] для извлечения заголовка сценария и значений результата из Scenario.Context - или везде, где вы можете их получить - и записи их в текстовый файл в формате значений, разделенных запятыми.
Интегрируйте этот процесс регистрации результатов CSV в проект SpecFlow, содержащий тесты, результаты которых вы хотите показывать в DevOps Azure.
CSV должен выглядеть примерно так:
DemoScenario_01 Lorem ipsum dolor sit amet consectetur adipiscing elit, Pass
DemoScenario_02 Sed do eiusmod tempor incididunt ut labore et dolore, Pass
DemoScenario_03 Magna aliqua Ut enim ad minim veniam quis, Pass
DemoScenario_04 Nostrud exercitation ullamco laboris nisi ut aliquip, Pass
DemoScenario_05 Ex ea commodo consequat Duis aute irure dolor in, Pass
DemoScenario_06 Reprehenderit in voluptate velit esse cillum dolore eu, Pass
DemoScenario_07 Fugiat nulla pariatur Excepteur sint occaecat cupidatat, Pass
DemoScenario_08 Non proident sunt in culpa qui officia semper, Pass
DemoScenario_09 Deserunt mollit anim id est laborum arcu semper, Pass
DemoScenario_10 Orci a scelerisque purus semper eget Ornare arcu dui vivamus, Pass
- Создайте отдельный простой "фиктивный" проект, содержащий только один класс, имеющий один работающий метод NUnit "test", который ничего не делает, кроме Assert.Pass (). Для этого проекта должны быть установлены пакеты NUnit и NUnit3TestAdapter NuGet.
Класс должен выглядеть примерно так:
namespace DemoNunit
{
public class Tests
{
[Test]
public static void DemoTest005()
{
Assert.Pass();
}
}
}
Создайте репозиторий Git-кода AzOv DevOps для решения этого «фиктивного» проекта и отправьте его в репозиторий.
Создайте новый конвейер Azure, сконфигурированный для сборок CI, который будет автоматически запускаться, когда фиксации в «пустом» проекте NUnit помещаются в репозиторий. Сконфигурируйте конвейер, чтобы иметь шаг теста Visual Studio под названием «SpecFlow Tests», который ищет dll, содержащую этот единственный тест NUnit. Назовите этот конвейер в соответствии с вашим проектом «SpecFlow» или функциональностью, которую он тестирует, поскольку этот конвейер на самом деле будет отображать эти результаты в области Builds-> Tests.
В новом отдельном проекте "convert" создайте процесс, который будет читать простой файл результатов CSV-вывода из вашего проекта "SpecFlow" и записывать новый файл .cs поверх существующего в " пустышка », в котором находится тест NUnit.
Единственный метод теста NUnit в проекте «фиктивный» теперь будет заменен несколькими методами, по одному для каждого результата, который был зарегистрирован в CSV. Эти методы будут названы как guids минус любые тире, и префикс с буквой, чтобы сделать их действительными именами методов C #. Цель состоит в том, чтобы иметь неповторяющиеся имена методов. Фактические имена тестовых сценариев SpecFlow будут сохранены в атрибутах NUnit TestCase TestName. Assert.Pass () или Assert.Fail () будут использоваться для соответствующих значений результатов, считанных из файла CSV. Скомпилируйте этот «конвертированный» проект в исполняемый файл.
Я пропустил код для чтения результатов CSV ...
namespace CreateCsFile
{
public static class CsFile
{
public static string OpenClass =
"using NUnit.Framework;" +
"namespace DemoNunit" +
"{" +
" public class Tests" +
" {";
public static string CloseClass =
" }" +
"}";
public static string TestMethod =
" [Test, TestCase(TestName = \"UniqueNameAttribute\")]" +
" public static void MethodName()" +
" {" +
" Assert.Result();" +
" }";
public static void LogListOfResults(
List<Test> resultsList)
{
Log.CsharpFile(OpenClass);
foreach (var result in resultsList)
{
Outcome.IsValid(result.Result);
var testMethod =
TestMethod.Replace(
"UniqueNameAttribute",
result.Name).
Replace(
"Result",
result.Result).
Replace("MethodName",
"a" + Guid.NewGuid().
ToString().
Replace("-",""));
Log.CsharpFile(testMethod);
}
Log.CsharpFile(CloseClass);
}
public static void ConvertCsvResultsToNunitResults()
{
LogListOfResults(
ParseCsv.ResultsSheet());
}
}
}
Журнал класса ...
namespace CreateCsFile
{
public class Log
{
public static string WasFileRemoved
= "";
public static string CsFileToggle
= "True";
public static string CsFile
= "C:\\Projects\\DemoNunit\\Tests.cs";
public static void CsharpFile(
string nunitData)
{
if (CsFileToggle.ToUpper()
== "TRUE")
{
if (string.IsNullOrEmpty(
WasFileRemoved))
{
RemoveExistingCsFile();
}
var log = !File.Exists(CsFile) ?
new StreamWriter(CsFile) :
File.AppendText(CsFile);
log.WriteLine(nunitData);
log.Close();
}
}
public static void RemoveExistingCsFile()
{
if (CsFileToggle.ToUpper()
== "TRUE")
{
WasFileRemoved = "True";
try
{
var fileInfo =
new FileInfo(CsFile);
fileInfo.Attributes =
FileAttributes.Normal;
File.Delete(fileInfo.FullName);
}
catch
{
throw new Exception(
@"Unable to delete existing csharp file...");
}
}
}
}
}
Гадкий вывод:
namespace DemoNunit{ public class Tests {
[Test, TestCase(TestName = "DemoScenario_01 Lorem ipsum dolor sit amet consectetur adipiscing elit")] public static void aa5f7fd239d6a40878780bc6c81f3a18b() { Assert. Pass(); }
[Test, TestCase(TestName = "DemoScenario_02 Sed do eiusmod tempor incididunt ut labore et dolore")] public static void aa9882fa95b17499eb9386b20a7ff303d() { Assert. Pass(); }
[Test, TestCase(TestName = "DemoScenario_03 Magna aliqua Ut enim ad minim veniam quis")] public static void a440c25f8c3c24e92ad90224da56bafda() { Assert. Pass(); }
[Test, TestCase(TestName = "DemoScenario_04 Nostrud exercitation ullamco laboris nisi ut aliquip")] public static void ab2c3cc6997df4a42b0992128f63358f7() { Assert. Pass(); }
[Test, TestCase(TestName = "DemoScenario_05 Ex ea commodo consequat Duis aute irure dolor in")] public static void a2c9f744dcd2c42c99cb6e288cf09fc78() { Assert. Pass(); }
[Test, TestCase(TestName = "DemoScenario_06 Reprehenderit in voluptate velit esse cillum dolore eu")] public static void a294422ae029049f9ac4be6f9bb4529cc() { Assert. Pass(); }
[Test, TestCase(TestName = "DemoScenario_07 Fugiat nulla pariatur Excepteur sint occaecat cupidatat")] public static void aa2dcdf889ffe4e46b57a73882d6f1a68() { Assert. Pass(); }
[Test, TestCase(TestName = "DemoScenario_08 Non proident sunt in culpa qui officia semper")] public static void a891c43376a5049f89ad75b70fa0a543f() { Assert. Pass(); }
[Test, TestCase(TestName = "DemoScenario_09 Deserunt mollit anim id est laborum arcu semper")] public static void aa8da317895214abc966c229c832c162f() { Assert. Pass(); }
[Test, TestCase(TestName = "DemoScenario_10 Orci a scelerisque purus semper eget Ornare arcu dui vivamus")] public static void aa9accb0c9c1b4918b76bc75ff2f2e835() { Assert. Pass(); }
}}
Теперь выполните следующие действия:
- выполнить тесты вашего проекта "SpecFlow" через командную строку, используя
NUnit консоль TestRunner (она должна быть настроена для удаления CSV
вывод в какое-то место, например c: \ Temp)
- выполните ваш проект "convert", который должен быть настроен для чтения
CSV в c: \ Temp и обновите файл .cs в проекте "dummy"
везде, где его клонированное репо существует на диске
- через аргументы командной строки, сделайте git commit и отправьте в репозиторий
изменить, что exe "convert" сделал в .cs файл "dummy" проекта
Теперь конвейер Azure будет создавать и отображать результаты тестовых выполнений проекта SpecFlow в виде «Тестов SpecFlow» с использованием имен и результатов, которые он хранит в CSV (у меня также есть некоторые демонстрационные идентификаторы).
Есть разные способы настройки; один из способов:
- поместите ваш проект SpecFlow в репозиторий git и создайте конвейер CI
за это
- добавить набор шагов сборки для выполнения тестов через командную строку
- добавить шаг для вызова exe-файла "convert", который был помещен в
исправлено расположение в окне сборки и обновлен файл «фиктивного» проекта, в котором он размещен на отдельной виртуальной машине в общей папке
- добавить шаг для добавления последнего обновления проекта "dummy" в git repo
Этот конвейер теперь будет автоматически запускаться при коммитах, переданных в его репо, и процесс автоматически преобразует результаты SpecFlow в результаты NUnit, запускает вторичный конвейер и показывает результаты SpecFlow в области Builds-> Tests той секунды pipleine. Первый конвейер не даст результатов, вы всегда будете смотреть на второй конвейер, чтобы увидеть их.
Для поддержки других / других проектов "SpecFlow" таким образом ... они, вероятно, могли бы совместно использовать часть "convert", но ее необходимо улучшить, чтобы иметь возможность передавать в нее местоположение объекта. CS файл, который он обновлял. Затем вы можете создать отдельные «фиктивные» проекты (и, конечно, связанные репозитории / конвейеры) для каждого «SpecFlow» проекта, для которого вы хотите увидеть результаты таким способом. Я еще не дошел до этого, поскольку сейчас я делаю это только для одного проекта.