fatalAssertNotError-like-method в модульном тесте MATLAB - PullRequest
1 голос
/ 21 сентября 2019

Я пишу набор тестов на основе классов в MATLAB для пакета обработки временных рядов.Первый тест в моем наборе должен проверить, существует ли соединение с базой данных Haver на сетевом диске.Если соединение не существует, то первый тест должен прервать оставшуюся часть пакета, используя один из методов fatalAssert.

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

У меня есть набор тестов родительского класса, который выполняет общие тесты для всех источников.Затем я наследую этот родительский класс в определенные наборы тестов дочернего класса и устанавливаю конкретные параметры в их соответствующем методе TestMethodSetup.Одним из этих параметров является анонимная функция connfun и местоположение connloc, которые я использую в родительском классе для проверки соединения.Причина, по которой я это делаю, заключается в том, что родительские тесты выполняются первыми, поэтому мне придется ждать завершения всех из них, если я хочу проверить соединение в дочернем классе.

Это также усложняет порядоквыполнение.Если я хочу присвоить connfun в дочернем классе, тогда я должен использовать либо TestMethodSetup, либо TestClassSetup дочернего класса (открытый для рекомендаций, по которым лучше здесь), и поместить этот тест соединения в Test метод родительского класса.Я заметил, что если бы я поместил checkConn в TestMethodSetup и TestClassSetup родительского класса, который выполнялся до дочернего класса, я не смог бы пройти анонимную функцию, и тест был бы неполным.

Отложив предыдущую точку на мгновение, это была моя первая попытка написания теста в родительском классе (обратите внимание, что я использовал fatalAssertEqual вместо fatalAssertTrue, потому что isconnection() не возвращает логическое значение):

methods (Test)
    function checkConn(testCase)
        connloc = 'pathToHaverDatabase';
        connfun = @(x) isconnection(haver(x));
        testCase.fatalAssertEqual(connfun(connloc), 1);
    end
end

Вышеописанное работает при наличии соединения, но проблема, с которой я столкнулся, заключается в том, что, когда я не могу получить доступ к connloc, возникает ошибка во время вызова haver().Таким образом, вместо возврата 1 или 0 из isconnection() вызова, который я могу включить fatalAssertEqual, все checkConn ошибки из-за haver().Это приводит к тому, что остальные тесты выполняются (и терпят неудачу, и это именно то, чего я хочу избежать).

Моя следующая идея работает в обоих случаях, но она чувствует как плохой коди не не имеет спецификации анонимной функции, описанной выше.

methods (Test)
    function checkConn(testCase)
        connloc = 'pathToHaverDatabase';
        connfun = @(x) isconnection(haver(x));
        try
            isconn = connfun(connloc);
        catch
            isconn = 0;
        end
        testCase.fatalAssertEqual(isconn, 1)
    end
end

Когда я писал это, я не обязательно хотел различать отсутствие доступа к сетевому диску, невозможность вызова функции haver() и получение isconnection равным 0потому что последний случай охватывает все три.Но я понял, что если бы я их дифференцировал, то это было бы немного более надежно, но в нем по-прежнему отсутствовала анонимная функция, которую я мог бы передать от ребенка к родителю.fatalAssert метод (или что-то подобное), который завершает набор тестов, когда его ввод является ошибкой.Что-то, что можно было бы назвать fatalAssertNotError, но я не думаю, что это существует.Если бы это было так, последняя строка моей первой функции была бы просто testCase.fatalAssertNotError(connfun(connloc)), и мне не пришлось бы беспокоиться обо всех случаях.

Я очень открыт для динамического переписывания всей этой настройки теста, поэтомулюбые конкретные комментарии или общие советы приветствуются!

Ответы [ 2 ]

0 голосов
/ 23 сентября 2019

Прежде всего, я думаю, что пример fatalAssert является сильным вариантом использования для предоставления чего-то вроде fatalAssertNotError.Одна из причин, по которой он не является частью пакета, заключается в том, что многие / большинство людей не хотят проверять, не происходит ли что-то не так, они просто хотят вызвать код, и если он дает ошибку, он автоматически завершается неудачей для автора теста.и это намного проще.Тем не менее, другие типы квалификации, такие как фатальные утверждения и предположения, возможно, указывают на необходимость предоставить это, чтобы вы могли выбрать результат теста при наличии ошибки в тех случаях, когда вы не хотите, чтобы он потерпел неудачу (например, с предположениями)или вы хотите, чтобы он «сильнее» потерпел неудачу, как в случае фатальных утверждений.

При этом я все еще не убежден, что вы не можете достичь того, что в конечном итоге пытаетесь сделать без него.У меня есть вопрос, почему вы не можете использовать TestClassSetup.Мне не совсем понятно, почему вы не смогли настроить в производном тестовом классе то поведение, которое вам нужно.Например, работает ли что-то подобное?

classdef BaseTest < matlab.unittest.TestCase
    properties(Abstract)
        connloc
        connfun
    end
    methods(TestClassSetup)
        function validateConnection(testCase)
            % If this errors it behaves like an assertion (not fatal assertion)
            % and fails all tests in the test class. If it doesn't error but
            % doesn't return 1 then the assertion failure will occur.
            testCase.assertEqual(connfun(connloc), 1, 
                'Could not establish a connection to the database'); 
        end
    end
end

classdef DerivedTest < BaseTest
    properties
        connloc = 'pathToHaverDatabase';
        connfun = @(x) isconnection(haver(x));
    end
    methods(Test)
        function testSomething(testCase)
            % Have at least one test method to test it out
        end
    end
end

Надеюсь, это поможет!

0 голосов
/ 23 сентября 2019

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

methods (Test)
  function checkConn(testCase)
    connloc = 'pathToHaverDatabase';
    function res = connfun(x)
      try
        res = isconnection(haver(x));
      catch
        res = false
      end
    end
    testCase.fatalAssertEqual(connfun(connloc), 1);
  end
end

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

Альтернативой является помещение функции в конец файла, вне блока classdef:

classdef ...
%...
methods (Test)
  function checkConn(testCase)
    connloc = 'pathToHaverDatabase';
    function res = connfun(x)
      try
        res = isconnection(haver(x));
      catch
        res = false
      end
    end
    testCase.fatalAssertEqual(connfun(connloc), 1);
  end
end
%...
end

function res = connfun(x)
  try
    res = isconnection(haver(x));
  catch
    res = false
  end
end

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...