C++ или D: идиома для разделения классов без динамической отправки?

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

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

class MyDependency
{
    void someMethod();
}

class MyUnit
{
    // Concrete type reference of MyDependency allows 
    // to bypass the dynamic dispatch
    this(MyDependency mayBeAMock)
    {
        mayBeAMock.someMethod();
    }

    unittest
    {
        // Now how can I get a mock of my dependency without to instantiate it.
        auto dep = someBlackMagic.getMock();
        auto uut = new MyUnit(dep);
    }
}

Существует ли лучший способ для модульного тестирования классов без учета затрат на динамическую диспетчеризацию при производстве. В случае необходимости я мог бы позволить себе эту стоимость для выполнения модульного тестирования, но не для выпуска продукта.

Я заинтересован в решениях D и C++.

2 ответа

Одна из техник, которую я очень часто использую в D, это замена политики во время компиляции:

private struct MyUtilImpl ( HTTPClient )
{
    void foo ( )
    {
        HTTPClient.makeRequest("url");
    }
}

version (unittest)
    alias MyUtil = MyUtilImpl!FakeHTTPClient;
else
    alias MyUtil = MyUtilImpl!RealHTTPClient;

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

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

2 идеи. Вы можете сделать MyUnit шаблоном и передать класс, который реализует (или имитирует) "someMethod"

Или, если ваши модульные тесты перестраивают тестируемый вами класс, вы можете определить Mock и реальную версию класса в отдельных файлах и условно включить / link в тот, который вам нужен.

Конечно, вы должны быть осторожны, чтобы не сделать вашу протестированную версию слишком отличной от не тестовой версии.

Другие вопросы по тегам