CSharp Allure classic NUnit with improvements

csharp
nunit
reporting
allure
Теги: #<Tag:0x00007fedb9753a88> #<Tag:0x00007fedb9753948> #<Tag:0x00007fedb9753808> #<Tag:0x00007fedb97536a0>

(Alexandr D ) #1

Доброго времени суток, коллеги!

Как мы все прекрасно знаем (или не все), поддержка и разработка Allure порта под C# не особо продвигается, за исключением энтузиастов вроде @unickq.

Я столкнулся со следующими проблемами/неудобствами в аллюре на C#:

  1. Невозможность добавления шагов/аттачей в [SetUp] и [TearDown] методах.
  2. Отсутствие нормальной возможности указания собственных:
  • Suite (самое неприятное)
  • SubSuite
  • Owner
  • Epic Suite
  • Parent Suite
  1. При выполнении действий в других потоках в рамках одного теста - allure падает с исключением.
    Т.е. если вы сделаете нечто подобное
    Task.Run( () => someMethod());
    и внутри данного метода будет вызвано логирование аллюр - выбросится исключение NullReferenceException.

  2. Отсутствие проигнорированных тест-кейсов/тестов в отчётах. (Кейсы, у которых прописано TestCaseData.Ignore(string).
    Для меня это оказалось критично, т.к. если мы не смогли найти подходящие тестовые данные из БД для кейса, он должен об этом кричать в отчете, а не отсутствовать там.

  3. Отсутствие нормального AddAttachment метода, который форматировал бы string в читабельный вид с отступами (json/xml).

Было что-то ещё, но оно не столь критичное, сейчас я уже не вспомню.

Я взял за основу проект https://github.com/unickq/allure-csharp-fork и добавил в него всю необходимую функциональность.

Переработанный мною C# allure имеет функциональность только для классического NUnit.
Если вы используете SpecFlow - не устанавливайте этот пакет, в нём нет ничего относящегося к SpecFlow, у вас всё сломается!

В будущем я добавлю нововведения для SpecFlow и сам SpecFlow, если это вообще кому-то будет нужно, кроме меня :slight_smile:

Итак…

Представляю вашему вниманию nuget пакет с переработанным C# Allure под классический NUnit: https://www.nuget.org/packages/Noksa.NUnit.Allure/

Некоторые методы я видоизменил, поэтому возможно придётся немного изменить их старую сигнатуру переходя с классического аллюра. Но это не точно. :slight_smile:

Кратко, как использовать данный allure и его некоторые новые фишки:

  1. ГЛАВНОЕ: Для включения логирования - необходимо унаследовать класс Allure.Commons.AllureReport базовым классом ваших тестов. Не нужно у каждого класса/метода писать какие-либо allure атрибуты:
public abstract class ABaseTestConfig : AllureReport

Либо непосредственно каждый класс с тестами, если базового нет.

  1. Для использования своего названия Suite, нужно добавить атрибут [AllureSuiteAttribute] у класса:
[AllureSuite(LoginPassNotExists)]
 public partial class MyTests: ABaseApiTestConfig
Своё название Suite

Внутри класса у методов можно использовать атрибут [AllureSubSuiteAttribute], для разделения на более мелкие Suite’s внутри одной большой [AllureSuiteAttribute]:

Пример SubSuites

  1. Для указания Epic Story для всего класса следует использовать атрибут [AllureEpicAttribute]:
[AllureEpic("Epic story")]
public partial class MyTests: ABaseApiTestConfig
Пример Epic Story

Соответственно, если в таком классе будут методы с атрибутами [AllureStoryAttribute], все они будут дочерними в следующем порядке:
Epic -> Feature > Story.

[AllureStory("С авторизацией")]
[AllureStory("Hey hey")]
public void Test()
Пример каскадности Story

image

  1. Атрибут [AllureOwnerAttribute] - устанавливает Owner’a теста\тест-кейса.

  2. Если у метода указаны атрибуты [AllureIssueAttribute], то в отчете в Suite класса добавится ещё один SubSuite с названием “With Defects”, где будет список тестов/кейсов класса, в которых этот атрибут присутствует.
    Сделано для быстрого поиска тестов с дефектами в указанных классах.
    В Story не добавляется, т.к. не вижу смысла в дублировании пока что:

SubSuite со всеми дефектами тестового класса

  1. Аналогично дефектам из 5 пункта, в Suite класса будут добавлены все проигнорированные тесты/кейсы этого класса (для этого ничего указывать не надо).

  2. Сам игнорированный тест имеет в отчете указанную причину, по которой это произошло:

Игнорированный тест

  1. Добавлена перегрузка метода AddAttachment()
    Выглядит так:
public AllureLifecycle AddAttachment(string name, AttachFormat type, string content, string fileExtension = "")

Используется для добавления отформатированных аттачей (xml/json), чтобы они выглядели читабельно, а не в одну строку:

Отформатированные аттачи

  1. Соответственно, теперь можно использовать добавление шагов/атачей в [SetUp] и [TearDown] методах.
    Пример Setup:
[SetUp]
public virtual void Setup()
        {
            AllureLifecycle.Instance.AddAttachment($"Screenshot [{DateTime.Now:HH:mm:ss}]",
                "image/png",
                Driver.TakeScreenshot().AsByteArray);
          ...
         }
    • Возможность использования потоков внутри одного теста для логирования в аллюр.
      Например: Task.Run( () => someMethod());
      Данный метод будет иметь начальным шагом не текущий шаг главного потока, а рутовый шаг отчета.
      Если вы в этом методе будете создавать steps с substeps - они будут создаваться корректно, внутри steps своего потока.

Итд…
Если возникнут проблемы/вопросы, пишите, буду рад помочь.

Это мой первый опыт выкладывания чего-либо в opensource, поэтому прошу отнестись с пониманием, если я где-то мог накосячить с пакетом :frowning:

Так же я не очень долго обкатывал новые атрибуты, поэтому если есть желающие быть бета-тестерами - велком :slight_smile:

Из известных проблем сейчас:

  1. В отчет попадают все проигнорированные тест-кейсы из тестового класса, даже если вы запускали только один тест в нём.


(Alexandr D ) #3

Разобрался с тем, как правильно пилить пакеты. :sunglasses:
Ну и по такому радостному событию обновил версию до 1.0.4.

Нововведения:
Добавлена поддержка net45/net451/net452 и netstandard2.0.


(Сергей Кузьмин) #4

… nuget хорошо но все-таки.

  • дайте пожалуйста линк на код вашего проекта на гитхаб

(Alexandr D ) #5

(Nick) #6

Для чего вклеивать все один проект? Тем более allure.csharp.fork, а не оригинальный allure.csharp


(Alexandr D ) #7

Не очень пронял про что именно речь.
Но вообще, в целом, я не люблю лишние зависимости, которые можно убрать. Именно поэтому я и взял fork как основу, чтобы не тянуть зоопарк.


(Nick) #8

Кор проект это лишняя зависимость?) Really :man_facepalming:

Форк это обрезанная версия старого allure-csharp, дабы была поддержка net45 без утяжеления ms json configuration, пока автор оригинала не решил таки переехать на newtonsoft json.

Потому собственно и вопрос - зачем внутри кор, так еще и не совсем валидный :slight_smile:

Как бы совместимость с уже сущевствующей инфраструктурой должна бы быть - если уж тут такая презентация, а не просто базовый класс для себя, делающий скрины в teardown :wink:


(Alexandr D ) #9

Если бы Вы чуточку внимательнее изучили мой проект, то заметили бы, что в core проекте (если я правильно Вас понял - то вы имеете в виду Commons) был так же изменен код классов AllureStorage.cs (для поддержки многопоточной записи в отчет в рамках одного теста) и AllureLifeCycle.cs, поэтому я не мог просто взять его и прицепить как зависимость.
Делать для изменённого core проекта отдельный nuget-пакет на мой взгляд было бы перебором, учитывая что он нигде кроме этого проекта не используется.
Это к вопросу зачем он там и почему не является зависимостью.

Изначально, собственно, это и делалось для себя с единственной целью - setup/teardown, но потом обросло большим функционалом.

Ну и, собственно, я не обещал совместимость с нынешней инфраструктурой, о чем и написал в первом сообщении. Она вполне может быть, просто я, честно говоря, не помню что я изменял в самом начале. :slight_smile:

И, опять же, если внимательнее изучить проект, то базовый класс в core-проекте не делает никаких скриншотов в teardown, он делает совсем другие вещи :wink: