Удаленка для jenkins+selenide+selenoid+allure+docker спецов на 2-3 часа в день. 100% remote! Присоединиться к проекту

Вопрос про логгирование Specflow в Nunit console

specflow
bdd
nunit
Теги: #<Tag:0x00007fedbb317a30> #<Tag:0x00007fedbb3178c8> #<Tag:0x00007fedbb317788>

(Nikitoz777) #1

Имеется такой тест, который запускают через NUnit GUI:


Те же самые логи будет выводить и NUnit console

Как видим, спекфлоу пушит логи в NUnit, который выводит логи в консоль.

Вопрос. Как можно выдернуть эти логи спекфлоу?


(Максим Таран) #2

Что значит выдернуть?


(Nikitoz777) #3

это значит завернуть в какойнить обьект, напрмиер стринг


(Максим Таран) #4

Так Вы же сами пишете сообщения в лог. Что-то я не могу конечную задачу понять.


(Nikitoz777) #5

пишу не я, а спекфлоу


(Максим Таран) #6

Давайте лучше конечную цель скажите, пока я не понимаю, что Вам надо. :slight_smile:


(Nikitoz777) #7

конечная цель - эти логи должны быть в тестрейле, а не в вижуал студии. обертка для пуша результатов в тестрейл уже есть.


(Максим Таран) #8

Мне кажется http://specflow.org/documentation/Reporting/ Вам поможет.


(Nikitoz777) #9

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


(Юрий Аксютин) #10

поиграйтесь со свойством this.ScenarioContext, точно не помню, возможно this.ScenarioContext.StepContext.StepInfo.Text
содержит описание текущего степа


(Nikitoz777) #11

описание ок, а результат по нему?


(Юрий Аксютин) #12

Окончательный вариант:

[BeforeStep]
public void LogStep()
{
   log.Debug(StepContext.StepInfo.Text);
}

......................................................................................

[AfterStep]
public void ErrorLog()
{
   if (this.ScenarioContext.TestError != null)
   {
      log.Debug(this.ScenarioContext.TestError.Message);
   }
}

В VS можно нажать клавишу F12 и посмотреть доступные свойства и методы у объекта,
например this.ScenarioContext:

public class ScenarioContext : SpecFlowContext
  {
    private static bool isCurrentDisabled;
    private static ScenarioContext current;
    private readonly ITestObjectResolver testObjectResolver;

    public static ScenarioContext Current
    {
      get
      {
        if (ScenarioContext.isCurrentDisabled)
          throw new SpecFlowException("The ScenarioContext.Current static accessor cannot be used in multi-threaded execution. Try injecting the scenario context to the binding class. See http://go.specflow.org/doc-multithreaded for details.");
        ScenarioContext current = ScenarioContext.current;
        return ScenarioContext.current;
      }
      internal set
      {
        if (ScenarioContext.isCurrentDisabled)
          return;
        ScenarioContext.current = value;
      }
    }

    public ScenarioInfo ScenarioInfo { get; }

    public ScenarioBlock CurrentScenarioBlock { get; internal set; }

    public Exception TestError { get; internal set; }

    public IObjectContainer ScenarioContainer { get; }

    internal TestStatus TestStatus { get; set; }

    internal List<string> PendingSteps { get; }

    internal List<StepInstance> MissingSteps { get; }

    internal Stopwatch Stopwatch { get; }

    public ScenarioStepContext StepContext
    {
      get
      {
        return this.ScenarioContainer.Resolve<IContextManager>().StepContext;
      }
    }

    internal ScenarioContext(IObjectContainer scenarioContainer, ScenarioInfo scenarioInfo, ITestObjectResolver testObjectResolver)
    {
      this.ScenarioContainer = scenarioContainer;
      this.testObjectResolver = testObjectResolver;
      this.Stopwatch = new Stopwatch();
      this.Stopwatch.Start();
      this.CurrentScenarioBlock = ScenarioBlock.None;
      this.ScenarioInfo = scenarioInfo;
      this.TestStatus = TestStatus.OK;
      this.PendingSteps = new List<string>();
      this.MissingSteps = new List<StepInstance>();
    }

    internal static void DisableSingletonInstance()
    {
      ScenarioContext.isCurrentDisabled = true;
      Thread.MemoryBarrier();
      ScenarioContext.current = (ScenarioContext) null;
    }

    public void Pending()
    {
      throw new PendingStepException();
    }

    public object GetBindingInstance(Type bindingType)
    {
      return this.testObjectResolver.ResolveBindingInstance(bindingType, this.ScenarioContainer);
    }
  }

(Nikitoz777) #13

сейчас опробую и отпишу


(Nikitoz777) #14

подход хороший но неясно как выводить TABLE в степах


(Nikitoz777) #15

вот этот тейбл


(Юрий Аксютин) #16

Я показал направление где искать эти свойства:
ScenarioContext.StepContext.StepInfo.Table
возможно, есть свойство, которое выводит сразу и описание и таблицу(что-то типа toString())
Надо приложить немного усилий и почитать документацию))


(Nikitoz777) #17

дело в том что это свойство представлено как Table обьект, а вывести его в читаемом виде - нужно постараться(


(Юрий Аксютин) #18

Вот так преобразуется Specflow table to C# объкт

public static class TableHelpers
    {
        public static Dictionary<string, string> ToDictionaryFromTableWithoutHeader(this Table table)
        {
            var dictionary = new Dictionary<string, string>();
            foreach (var row in table.Rows)
            {
                dictionary.Add(row[0], row[1]);
            }

            return dictionary;
        }

        public static Dictionary<string, string> ToDictionaryFromTableWithHeader(this Table table)
        {
            var headers = new List<string>(table.Header.ToArray());
            var dictionary = new Dictionary<string, string>();
            foreach (var row in table.Rows)
            {
                for (int j = 0; j < row.Count; j++)
                {
                    dictionary.Add(headers[j], row[j]);
                }
            }

            return dictionary;
        }

        public static List<Dictionary<string, string>> ToListOfDictionaryFromTableWithHeader(this Table table)
        {
            var headers = new List<string>(table.Header.ToArray());
            List<Dictionary<string, string>> result = new List<Dictionary<string, string>>();
            foreach (var row in table.Rows)
            {
                Dictionary<string, string> temp = new Dictionary<string, string>();
                for (int j = 0; j < row.Count; j++)
                {
                    temp.Add(headers[j], row[j]);
                }

                result.Add(temp);
            }

            return result;
        }

        public static List<string> SingleColumnToList(this Table table)
        {
            List<string> result = new List<string>();

            foreach (var row in table.Rows)
            {
                result.Add(row[0]);
            }

            return result;
        }
    }

(Nikitoz777) #19

решил сделать немного по другому:
ScenarioContext.Current.StepContext.StepInfo.Table.ToString()


(Nikitoz777) #20

и теперь таблички в красивом виде в тестрейле. всекм спасибо