NUnit: как передать TestCaseData из нестатического метода?

мой тест не проходит из-за: Сообщение: имя источника, указанное в атрибуте TestCaseSourceAttribute, должно относиться к статическому полю, свойству или методу.

Это мой код:

const double MAX_DELTA = 0.01;
Qv_ges qv_ges_NE;
double Sum_Qv_ges_R_FL;
Qv_ges Qv_ges_Quer;

[SetUp]
public void init()
{
    qv_ges_NE = Din1946.Calc_Qv_ges_NE(205.7d);
    Sum_Qv_ges_R_FL = 15d + 15d + 15d + 15d + 15d + 10d + 10d + 10d + 10d + 10d + 10d + 10d;
    Qv_ges_Quer = Din1946.Calc_Qv_ges_Quer(qv_ges_NE, Sum_Qv_ges_R_FL);
}

public IEnumerable<TestCaseData> TestCases_A()
{
        yield return new TestCaseData(72.5, Qv_ges_Quer.FL.Value, MAX_DELTA);
        yield return new TestCaseData(169.17, Qv_ges_Quer.RL.Value, MAX_DELTA);
        yield return new TestCaseData(241.67, Qv_ges_Quer.NL.Value, MAX_DELTA);
        yield return new TestCaseData(314.17, Qv_ges_Quer.IL.Value, MAX_DELTA);
    }


    [TestCaseSource("TestCases_A")]
public void MethodA(double expected, double value, double latitude)
      { Assert.AreEqual(expected, value, latitude);}

Я использовал только статические тестовые методы, но теперь мне нужны такие данные, как: Qv_ges_Quer.IL.Value, _3 _...., поэтому я удалил статические

Как я могу использовать нестатический тестовый набор? Еще при отладке заметил, что сначала не входит в SetUp

Это мой старый код, который я хочу переорганизовать, надеюсь, вы знаете другой / лучший способ, чем описанный выше:

public void MethodA(){
  Qv_ges qv_ges_NE = Din1946.Calc_Qv_ges_NE(205.7d);

  double Sum_Qv_ges_R_FL = 15d + 15d + 15d + 15d + 15d + 10d + 10d + 10d + 10d + 10d + 10d + 10d;
  Qv_ges Qv_ges_Quer = Din1946.Calc_Qv_ges_Quer(qv_ges_NE, Sum_Qv_ges_R_FL);

  Assert.AreEqual(72.5, Qv_ges_Quer.FL.Value, MAX_DELTA);
  Assert.AreEqual(169.17, Qv_ges_Quer.RL.Value, MAX_DELTA);
  Assert.AreEqual(241.67, Qv_ges_Quer.NL.Value, MAX_DELTA);
  Assert.AreEqual(314.17, Qv_ges_Quer.IL.Value, MAX_DELTA);
}

person Perazim    schedule 07.09.2016    source источник
comment
Я должен признать, что Calc_Qv_ges_Quer() - статический метод   -  person Perazim    schedule 07.09.2016


Ответы (2)


По замыслу метод, свойство или поле, используемые TestCaseSourceAttribute, должны быть статическими. Это сделано для того, чтобы избежать необходимости создавать экземпляр класса фикстур во время загрузки тестов. Ваше приспособление создается только тогда, когда мы запускаем прогон - в случае графического интерфейса пользователя, каждый раз, когда мы запускаем прогон - и его время жизни ровно столько, сколько требуется для запуска этого приспособления.

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

Единственный способ использовать здесь методы экземпляра - использовать конструктор TestCaseSourceAttribute (Type sourceType), где sourceType реализует IEnumerable и напрямую возвращает данные вашего тестового примера. Если вы используете это, я рекомендую использовать другой класс из вашего TestFixture. Это не обязательно. Если вы используете один и тот же класс, во время загрузки и выполнения будут созданы разные экземпляры, которые никак не связаны друг с другом. Многие разработчики в конечном итоге сбиваются с толку и пытаются оставить состояние во время загрузки для использования в тестах. Это не сработает.

person Charlie    schedule 07.09.2016
comment
Итак, я не могу получить доступ к объекту с помощью TestCaseSource, потому что его TestCaseSource статичен? Извините, я этого не понимаю: / - person Perazim; 30.09.2016
comment
Я ответил на ваш вопрос на том основании, что вы хотите, чтобы метод исходных данных был нестатическим. Это невозможно. Ничто не мешает тестовым методам быть экземплярами. - person Charlie; 01.10.2016
comment
Раньше у нас было много TestCaseSources, которые использовали свойство TestData тестовой оснастки для поиска набора файлов тестовых примеров. Выявить эту логику будет нелегко. Раньше это работало в основном нормально с NUnit2 (за исключением того, что ненужные источники тестовых примеров вызывались для тестов, даже не предназначенных для запуска в этом сеансе), и это серьезное изменение при миграции на NUnit3. - person hypersw; 23.03.2017
comment
Хуже всего, когда TestCaseSource вызывает виртуальный метод, который переопределяется в производных классах. Для этого я не сразу знаю, что мне делать. - person hypersw; 23.03.2017
comment
См. Также мой ответ об использовании для этого функторов. - person metal; 01.02.2019
comment
@ Чарли, в каком состоянии это? Можно ли использовать нестатические методы для случаев, когда мне нужны тестовые данные с использованием чего-то, созданного в методе [SetUp]? - person ceco; 25.02.2020
comment
Не то, чтобы я знал об этом, но вы должны спросить на GitHub, чтобы люди, работающие над NUnit, могли дать окончательный ответ. - person Charlie; 26.02.2020

????‍♀️ Реакция зомби, но лучше поздно, чем никогда. ????

Другой способ добиться этого - сделать так, чтобы ваш источник данных тестового примера возвращал объект функции, который принимает нестатические элементы, которые вам нужны, в качестве своих параметров. Затем ваш тест вызывает это для создания данных, которые вы хотите, чтобы NUnit мог передать вам.

В вашем случае это выглядит примерно так:

private static IEnumerable<TestCaseData> GetTestDataA()
{
    yield return new TestCaseData(72.5,   new Func<Qv_ges, double>( qvGesQuer => qvGesQuer.FL.Value ), MAX_DELTA);
    yield return new TestCaseData(169.17, new Func<Qv_ges, double>( qvGesQuer => qvGesQuer.RL.Value ), MAX_DELTA);
    yield return new TestCaseData(241.67, new Func<Qv_ges, double>( qvGesQuer => qvGesQuer.NL.Value ), MAX_DELTA);
    yield return new TestCaseData(314.17, new Func<Qv_ges, double>( qvGesQuer => qvGesQuer.IL.Value ), MAX_DELTA);
}

[TestCaseSource( nameof(GetTestDataA) )]
public void MethodA( double expected, Func<Qv_ges, double> getValue, double latitude)
{ 
    Assert.AreEqual( expected, getValue( Qv_ges_Quer ), latitude );
}

Если вам нужно несколько параметров, добавьте их к параметрам функтора и лямбда или рассмотрите возможность передачи вместо них this. Если вам нужно несколько возвращаемых значений, сделайте так, чтобы объект функции возвращал кортеж:

new Func<Qv_ges, (double, double)>( qvGesQuer => (qvGesQuer.RL.Value, qvGesQuer.IL.Value) )

Другой подход - передать nameof() строк в качестве параметров теста и использовать отражение для получения значений этих параметров.

person metal    schedule 01.02.2019