Обработка исключений контекста теста MSTest - PullRequest
7 голосов
/ 14 января 2010

Есть ли способ, которым я могу получить исключение, которое было обработано инфраструктурой MSTest с использованием TestContext или какого-либо другого метода в базовом классе тестирования?

Если в одном из моих тестов возникает необработанное исключение, я бы хотел прокрутить все элементы в словаре исключения. Словарь и отобразить их в результатах теста, чтобы помочь мне выяснить, почему тест не удался (мы обычно добавляем исключение данных, чтобы помочь нам отладить в производственной среде, поэтому я хотел бы сделать то же самое для тестирования).

Примечание: я не проверяю, что исключение было ПРЕДПОЛАГАЕТСЯ, чтобы произойти (у меня есть другие тесты для этого), я проверяю действительный случай, мне просто нужно просмотреть данные исключения.

Вот пример кода того, о чем я говорю.

[TestMethod]
public void IsFinanceDeadlineDateValid()
{
    var target = new BusinessObject();
    SetupBusinessObject(target);

    //How can I capture this in the text context so I can display all the data 
    //in the exception in the test result...

    var expected = 100;
    try
    {
        Assert.AreEqual(expected, target.PerformSomeCalculationThatMayDivideByZero());
    }
    catch (Exception ex)
    {
        ex.Data.Add("SomethingImportant", "I want to see this in the test result, as its important");
        ex.Data.Add("Expected", expected);
        throw ex;
    }

}

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

Однако, если тест не пройден, 99% времени я перезапускаю его, и я ничего не могу отладить без этой информации. Я также хотел бы сделать это на глобальном уровне, чтобы в случае неудачи любого теста я получал информацию в результатах теста, а не делал это для каждого отдельного теста.

Вот код, который поместит информацию об исключении в результаты теста.

    public void AddDataFromExceptionToResults(Exception ex)
    {
        StringBuilder whereAmI = new StringBuilder();
        var holdException = ex;
        while (holdException != null)
        {
            Console.WriteLine(whereAmI.ToString() + "--" + holdException.Message);
            foreach (var item in holdException.Data.Keys)
            {
                Console.WriteLine(whereAmI.ToString() + "--Data--" + item + ":" + holdException.Data[item]);
            }

            holdException = holdException.InnerException;
        }
    }

Ответы [ 3 ]

3 голосов
/ 03 мая 2010

Я сталкивался с той же проблемой, но, похоже, поддержки нет. Вы даже не можете использовать обработчик необработанных исключений ApplicationDomain, так как, если MSTEST не перехватит исключения до того, как они всплыли так далеко, он сам вылетит.

Возможное решение:

    private delegate void TestImplDelegate();

    private void RunTestWithExceptionLogging(TestImplDelegate testImpl)
    {
        try
        {
            testImpl();
        }
        catch (Exception e)
        {
            string message = e.Message; // don't warn about unused variables

            // do logging here
        }
    }

    [TestMethod]
    public void test1()
    {
        RunTestWithExceptionLogging(test1Impl);
    }
    private void test1Impl()
    {
        // test code goes here

        throw new Exception("This should get logged by the test wrapper.");
    }

    [TestMethod]
    public void test2()
    {
        RunTestWithExceptionLogging(test2Impl);
    }
    private void test2Impl()
    {
        // test code goes here

        throw new Exception("This should get logged by the test wrapper.");
    }

Это, конечно, не оптимально, но, по крайней мере, таким образом у вас нет нескольких копий кода обработчика исключений.

Я бы порекомендовал подать запрос на добавление функции для этого на http://connect.microsoft.com/ (или посмотреть, если кто-то еще запросил его, и добавить свой голос.)

1 голос
/ 22 июля 2014

Вот «чистая» работа, которая помещает исключение в свойство TestBase.TestContext (или где вы хотите в своем экземпляре TestBase).

В примере используется postsharp (который является библиотекой AOP) для внедрения try-catch в код во время компиляции. Он внедрит все методы, которые имеют атрибут [TestMethod]. - бесплатное издание Postsharp сделает работу, без необходимости по лицензии.

Первое, что вам нужно сделать, это создать атрибут AOP. Атрибуты определяют, что будет сделано в случае исключения, и + определяют условия для инъекции, вот как вы это делаете:

/// <summary>
/// Catch exceptions of tests and save them in <see cref="TestBase"/> under TestContext.Properties. This is done since MSTEST does not supply any mechanism to catch tests exceptions.
/// </summary>
[SerializableAttribute]
public class CodedTestsExceptionsHandlingAop : OnExceptionAspect
{
    /// <summary>
    /// The name of the property that will be added to the test context properties object.
    /// </summary>
    public const string FailureExceptionProerty = "FailureException";

    /// <summary>
    /// Save the exception in a <see cref="TestBase"/> and rethrow.
    /// </summary>
    /// <param name="args"></param>
    public override void OnException(MethodExecutionArgs args)
    {
        var testBase = (Framework.TestBase) args.Instance;//The instance running the test inherits from TestBase.
        testBase.TestContext.Properties.Add("FailureException", args.Exception);

        args.FlowBehavior = FlowBehavior.RethrowException;
    }

    /// <summary>
    /// Make sure only test methods will get this AOP.
    /// </summary>
    /// <param name="method"></param>
    /// <returns></returns>
    public override bool CompileTimeValidate(MethodBase method)
    {
        if (method.IsDefined(typeof(TestMethodAttribute)))
            return true;

        return false;
    }
}

Во-вторых, вам нужно будет добавить следующий атрибут уровня сборки в ваш тестовый проект (в котором также должен быть установлен postsharp, если он не находится в том же проекте, что и ваша TestBase), это будет применять внедрение AOP поверх тестовая сборка:

[assembly: CodedTestsExceptionsHandlingAop(AttributeTargetTypes = "*", AttributeTargetElements = MulticastTargets.Method)]
0 голосов
/ 10 июля 2017

Если вы просто хотите протестировать ожидаемые исключения, вы можете использовать ExpectedExceptionAttribute

Я думаю, что возможность получить исключение для модульного теста было бы более полезно, когда оно является непредвиденным исключением, и вы хотите регистрировать или собирать дополнительную информацию об исключении, вместо того, чтобы полагаться на TestExplorer, чтобы найти проверку неудачной. тесты.

...