Модульные тесты Matlab чередуются между «pass» и «fail» (pass «нечетные» прогоны, fail при «четном») - PullRequest
1 голос
/ 23 апреля 2020

У меня есть несколько модульных тестов для кода, который выполняет очень незначительные манипуляции с изображениями (объединяя несколько маленьких изображений в большое изображение). Когда я запускал тесты, я заметил, что три из четырех из них потерпели неудачу в строке, где они читают изображение из каталога (не удается с ошибкой индекса вне границ).

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

Мой репозиторий организован следующим образом:

src/
    /* source code .m files are in here */

unit_tests/
    images/
        squares/
            - img1.png
            - img2.png
            ...
            - imgn.png
    - unit_tests.m

И в моей настройке есть строка (внутри unit_tests.m) для генерации и добавления путей для всего кода:

function tests = unit_tests()
    addpath(genpath('..'));    
    tests = functiontests(localfunctions);
end

Все модульные тесты имеют следующий формат:

function testCompositeImage_2x3(testCase)
    squares = dir('images/squares/*.png');
    num_images = length(squares);
    img = imread([squares(1).folder filesep squares(1).name]); % all same size squares
    rows = 2;
    cols = 3;
    buffer = 2;

    for idx = 1:num_images - (rows*cols)
        imarray = cell(1,(rows*cols));
        n = 1;
        for ii = idx:idx +(rows*cols) -1
            imarray{n} = imread([squares(ii).folder filesep squares(ii).name]);
            n = n + 1;
        end

        newimg = createCompositeImage(rows,cols,imarray, buffer);

        expCols = cols*size(img,1) + (cols+1)*2*buffer;
        expRows = rows*size(img,2) + (rows+1)*2*buffer;
        assert(checksize(newimg, expRows, expCols, 3) == true);
    end
end

("checkize" - это только что написанный мной помощник, который возвращает логическое значение b / c assert не сравнивает матрицы)

Когда я запускаю сеанс fre sh matlab и запускаю модульные тесты (используя кнопку «Run Tests» на вкладке редактора), они проходят с таким выводом:

>> runtests('unit_tests\unit_tests.m')
Running unit_tests
.......
Done unit_tests
__________


ans = 

  1×7 TestResult array with properties:

    Name
    Passed
    Failed
    Incomplete
    Duration
    Details

Totals:
   7 Passed, 0 Failed, 0 Incomplete.
   0.49467 seconds testing time.

Второй запуск (снова нажатием кнопки):

>> runtests('unit_tests')
Running unit_tests
..
================================================================================
Error occurred in unit_tests/testCompositeImage_2x2 and it did not run to completion.

    ---------
    Error ID:
    ---------
    'MATLAB:badsubscript'

    --------------
    Error Details:
    --------------
    Index exceeds array bounds.

    Error in unit_tests>testCompositeImage_2x2 (line 47)
        img = imread([squares(1).folder filesep squares(1).name]); % all same size
================================================================================
/*similar error info for the other two failing tests...*/
...
Done unit_tests
__________

Failure Summary:

     Name                               Failed  Incomplete  Reason(s)
    ==================================================================
     unit_tests/testCompositeImage_2x2    X         X       Errored.
    ------------------------------------------------------------------
     unit_tests/testCompositeImage_2x3    X         X       Errored.
    ------------------------------------------------------------------
     unit_tests/testCompositeImage_3x2    X         X       Errored.


ans = 

  1×7 TestResult array with properties:

    Name
    Passed
    Failed
    Incomplete
    Duration
    Details

Totals:
   4 Passed, 3 Failed (rerun), 3 Incomplete.
   0.0072287 seconds testing time.

Тот факт, что происходит сбой в основном в первой строке, потому что он ничего не читает из папки, заставляет меня подозревать, что даже когда другой 4 теста якобы пройдены, тыс. Они на самом деле не работают вообще. И, тем не менее, если я снова проведу тесты, они все пройдут. Запустите его в 4-й раз, и они снова не пройдут.

Сначала я подумал, что, возможно, модульные тесты выполнялись слишком быстро (только для чеков с четными номерами?), И раньше он выполнял модульные тесты. Функции addpath / genpath в настройке завершены, поэтому я добавил оператор pause и перезапустил тесты, но у меня возникла та же проблема, только в этот раз он подождал необходимое количество секунд, прежде чем продолжить и потерпеть неудачу. Если я запустлю его снова, нет проблем - все мои тесты пройдут.

Я совершенно не понимаю, почему это происходит; Я использую vanilla matlab (R2018a), работающий на машине с Win10, и у меня нет ничего необычного. Я чувствую, что вы должны иметь возможность запускать свои юнит-тесты столько раз, сколько захотите, и ожидать того же результата! Есть что-то, что я просто как-то упустил? Или это какая-то странная особенность?

1 Ответ

1 голос
/ 23 апреля 2020

Добавление моего исправления на тот случай, если кто-то столкнется с той же проблемой.

Как указал Крис, что-то в строке

addpath(genpath('..'));

вызывает GUI до go в странное состояние, когда нажатие кнопки «Выполнить тесты» чередует вызовы runtests('unit_tests\unit_tests.m') и runtests('unit_tests'), что, в свою очередь, приводит к попеременному прохождению тестов и неудаче.

Замена этой строки на следующую, кажется, разрешает проблема:

pth = fullfile(fileparts(fileparts(mfilename('fullpath'))),'src');
paths = regexp(genpath(pth), ';', 'split');
for idx = 1:length(paths) - 1 % last element is empty
    addpath(paths{idx});
end

Мне нужно было перезапустить matlab, чтобы изменения вступили в силу. Это сработало для моей установки с использованием r2018a на Win10.

...