MSTest & AppDomains

В моем проекте я заметил, что во время выполнения модульных тестов в VSTS2008 увеличивается его потребляемая память VSTestHost. Поскольку у меня очень много тестов в моем решении, это в конечном итоге приводит к OutOfMemroyException. Это выглядит очень странно для меня, поскольку я был уверен, что MSTest создает новый AppDomain для каждого unit test. Иначе как это будет reset статические поля? Но если AppDomain создается для каждого теста, а память не должна течь. Но это так.

Итак, вопрос: должен ли VS создавать AppDomain для каждого тестового класса или нет? Если да, то как я могу проверить, что он это делает. Я пробовал отслеживать через оснастку ProcessExpolorer и Performance. Значение "Total addomain unloaded" всегда равно 0 во время тестового прогона.

Ответ 1

Я не думаю, что движок unit test создает новый AppDomain для каждого теста. Поскольку создание AppDomain является относительно дорогостоящей операцией, выполнение этого для каждого теста значительно замедлит выполнение модульных тестов!

Visual Studio 2008 использует отдельный исполняемый файл под названием vstesthost.exe для запуска модульных тестов. VS общается с vstesthost.exe(как это делает я не знаю), чтобы сказать, какие тесты следует запускать. vstesthost.exe возвращает результаты выполнения VS, который отображает эти результаты.

Если вы получаете OutOfMemoryExceptions при выполнении своих модульных тестов, я бы сказал, что сильный индикатор того, что ваш тестируемый код на самом деле не очищает вещи. Вы уверены, что не сохраняете ручки для неуправляемых объектов/памяти? Я бы рекомендовал запустить ваши модульные тесты в рамках анализа производительности (вы можете это сделать, найдя unit test в разделе "Тестирование", щелкнув правой кнопкой мыши его и выбрав "Создать сессию производительности" ). Это может пролить некоторый свет, по крайней мере, на распределение объектов.

Ответ 2

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

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

Ответ 3

Я ошибался в том, что для каждого unittest есть отдельные AppDomains.

Здесь доказательства: одиночный

public class Singleton
{
    public static Singleton Instance = new Singleton();

    private Guid _token;
    private Singleton()
    {
        _token = Guid.NewGuid();
    }

    public Guid Token
    {
        get { return _token; }
    }
}

и два теста:

[TestClass]
public class UnitTest2
{
    [TestMethod]
    public void TestMethod1()
    {
        Console.WriteLine(Singleton.Instance.Token);
    }
}
[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        Console.WriteLine(Singleton.Instance.Token);
    }
}

Во время выполнения обоих тестов выводится один и тот же guid.

Ответ 4

Видите ту же проблему с большими пробными запусками. Моя теория такова. Утомление памяти в этом случае связано с тем, что файлы результатов теста MSTest являются XML. Поэтому он должен сохранять все результаты журнала в памяти до конца тестового запуска до сериализации на диск. Ура для XML: -)

Я опубликовал эту проблему как связать проблему некоторое время назад, и она должна была быть исправлена ​​в MSTest 10 (идет 64 бит), но я пока не смогли проверить это из-за всех других проблем, которые мы переместили на VS2010 и .NET 4.0.

Ответ 5

Это не похоже на решение в MSTest 2010. У меня много подобных проблем. Почему сбор мусора не работает в unit test?

Мое понимание заключалось в том, что структура UT позаботилась об утилизации всех выполненных тестов, но это не похоже на некоторые шаблоны singleton, которые у нас есть в коде.

Ответ 6

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