Unit Test не работает при запуске All, но не в запуске выбранных тестов со всеми выбранными
Я получаю какое-то странное поведение. Если я нажму "Запустить все" в Проводнике, то 1 из моих тестов модулей завершится с ошибкой, но если я выберу все тесты и нажмите "Запустить выбранные тесты", то пройдет unit test.
Тест, который терпит неудачу, вызывает ошибку отражения: System.Reflection.TargetException: Non-static method requires a target.
для типа, который определен в коде dll, который я тестирую. Кажется, что нет ничего странного в классе - в DLL есть много других классов, которые отражают радость. Я включил трассировку тестового стека ниже.
NB Это сложный тест - он считывает входы и ожидаемые ответы из файла .xlsx, заполняет LocalDb данными из xlsx, выполняет вычисления с использованием данных в LocalDB, а затем сравнивает вычисленные с ожидаемыми значениями. Однако, как я уже сказал, он работает и работает, когда я запускаю все тесты (используя select all > Run Selected Test).
Чем отличается Run All? Любые идеи будут оценены.
Я попробовал очистить и перестроить, не повезло. Ошибка отслеживания и регистрации событий показывает, что вызов GetValue бросает для каждого свойства, к которому я пытаюсь получить доступ к типу, но только при запуске "Запустить все" и только в этом типе? (если я поймаю ошибку, то все GetValues будут успешны для всех других типов).
Трассировка стека
Test Name: IT_CheckCashOnly1DepositOutputValues
Test FullName: Lib.AE.Tests.Integration.CalculationTests.IT_CheckCashOnly1DepositOutputValues
Test Source: c:\netreturn.co.za\Main\NetReturn\Lib.AE.Tests\IntegrationTests\CalculationTest.cs : line 23
Test Outcome: Failed
Test Duration: 0:00:00.1661906
Result Message:
Test method Lib.AE.Tests.Integration.CalculationTests.IT_CheckCashOnly1DepositOutputValues threw exception:
System.Reflection.TargetException: Non-static method requires a target.
Result StackTrace:
at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
at Lib.AE.Xlsx.XlsxHelper.Compare[T](T expected, T calculated, ExcelWorksheet ws, Int32 r, Int32 colStart, Boolean& valid) in c:\netreturn.co.za\Main\NetReturn\Lib.AE\Xlsx\XlsxHelper.cs:line 101
at Lib.AE.Xlsx.XlsxWorkSheet_SharePNL.CompareXlsx(ExcelPackage pck, List`1 expectedXlsx, ValuationCalculation calc) in c:\netreturn.co.za\Main\NetReturn\Lib.AE\Xlsx\XlsxSharePNL.cs:line 143
at Lib.AE.Tests.Integration.CalculationTests.CheckCalculationResults(String xlsxDocToLoad, WorkSheets testingScenarios) in c:\netreturn.co.za\Main\NetReturn\Lib.AE.Tests\IntegrationTests\CalculationTest.cs:line 64
at Lib.AE.Tests.Integration.CalculationTests.IT_CheckCashOnly1DepositOutputValues() in c:\netreturn.co.za\Main\NetReturn\Lib.AE.Tests\IntegrationTests\CalculationTest.cs:line 23
Решение
Итак, это оказалось (а) моей проблемой - моим unit test общим состоянием с другим unit test и (b) проблемой порядка. Имейте в виду, что это не очевидно, какой заказ TestExplorer выполнит ваши тесты. Я создал новый UnitTestProject с 2 x UnitTest.cs файлами и тремя TestMethods каждый i.e.:
UnitTest1.cs
[TestMethod]
public void ONE_AAA() {}
[TestMethod]
public void ONE_BBB() {}
[TestMethod]
public void ONE_CCC() {}
UnitTest2.cs
[TestMethod]
public void TWO_CCC() {}
[TestMethod]
public void TWO_BBB() {}
[TestMethod]
public void TWO_AAA() {}
Затем выполнялись эти тесты с помощью двух методов: 1. (1) Выполнить все (2) Выбрать все и Запустить выбранные тесты и зарегистрировать порядок, в котором тесты были запущены TestExplorer. Результаты для Run Selected Tests довольно неинтуитивны:
-- Run All
2013-01-16 11:53:47.4062 INFO TestInitialize: ONE_AAA
2013-01-16 11:53:47.4122 INFO TestCleanup: ONE_AAA
2013-01-16 11:53:47.4122 INFO TestInitialize: ONE_BBB
2013-01-16 11:53:47.4122 INFO TestCleanup: ONE_BBB
2013-01-16 11:53:47.4122 INFO TestInitialize: ONE_CCC
2013-01-16 11:53:47.4282 INFO TestCleanup: ONE_CCC
2013-01-16 11:53:47.4282 INFO TestInitialize: TWO_CCC
2013-01-16 11:53:47.4282 INFO TestCleanup: TWO_CCC
2013-01-16 11:53:47.4282 INFO TestInitialize: TWO_BBB
2013-01-16 11:53:47.4282 INFO TestCleanup: TWO_BBB
2013-01-16 11:53:47.4282 INFO TestInitialize: TWO_AAA
2013-01-16 11:53:47.4282 INFO TestCleanup: TWO_AAA
-- Select All > Run Selected
2013-01-16 11:55:26.0139 INFO TestInitialize: TWO_BBB
2013-01-16 11:55:26.0139 INFO TestCleanup: TWO_BBB
2013-01-16 11:55:26.0249 INFO TestInitialize: ONE_BBB
2013-01-16 11:55:26.0249 INFO TestCleanup: ONE_BBB
2013-01-16 11:55:26.0249 INFO TestInitialize: TWO_AAA
2013-01-16 11:55:26.0249 INFO TestCleanup: TWO_AAA
2013-01-16 11:55:26.0249 INFO TestInitialize: TWO_CCC
2013-01-16 11:55:26.0249 INFO TestCleanup: TWO_CCC
2013-01-16 11:55:26.0249 INFO TestInitialize: ONE_CCC
2013-01-16 11:55:26.0249 INFO TestCleanup: ONE_CCC
2013-01-16 11:55:26.0249 INFO TestInitialize: ONE_AAA
2013-01-16 11:55:26.0249 INFO TestCleanup: ONE_AAA
Ответы
Ответ 1
В прошлом я был пойман с запуском нескольких модульных тестов тем, что порядок выполнения тестов не может быть в том порядке, в котором они объявлены в тестовом классе, и может фактически быть в порядке тестирования имя метода. например если у меня есть
[Test]
public void PreviousTest()
{
}
[Test]
public void LaterTest()
{
}
Затем LaterTest
запускается первым, поскольку его имя появляется перед PreviousTest
при заказе в алфавитном порядке.
Это не имеет значения, если все ваши тесты полностью независимы, но если они изменяют общие ресурсы, тогда вы можете получить необычное поведение, если бы ожидали, что изменения LaterTest
не повлияют на PreviousTest
из-за на него объявляется вторым.
Ответ 2
Убедитесь, что ваши члены инициализируются в области настройки, в противном случае они могут быть повторно использованы.
[TestFixture]
public class RegistrationInteractorTests
{
private IRegistrationService _registrationService;
private IRegistrationValidationService _registrationValidationService;
......
[SetUp]
public void Init()
{
_registrationService = A.Fake<IRegistrationService>();
_registrationValidationService = A.Fake<IRegistrationValidationService>();
}
....
}
//Неправильный путь будет таким:
[TestFixture]
public class RegistrationInteractorTests
{
protected readonly IRegistrationService _registrationService = A.Fake<IRegistrationService>();
protected readonly IRegistrationValidationService _registrationValidationService =
A.Fake<IRegistrationValidationService>();
[SetUp]
public void Init()
{
}
Ответ 3
Ваш метод [TestInitialize]
запускается перед каждым тестом. Удалите из него любой код, зависящий от одного теста, и поместите его в отдельный тест.