代码之家  ›  专栏  ›  技术社区  ›  rescdsk

在没有命名空间污染的情况下运行MATLAB代码片段

  •  4
  • rescdsk  · 技术社区  · 14 年前

    我正在写Python的一个版本 doctest 试车员, for MATLAB

    % >> I = 5 + 33; % expect no output
    % >> I
    % 
    % I =
    % 
    %     38
    %
    

    为了运行测试,我对搜索测试的REGEX进行了循环匹配。每一场比赛,我 evalc

    for I = 1:length(examples)
        try
            got = evalc(examples(I).source);
        catch exc
            got = ['??? ' exc.message];
        end
    
        % process the result...
    end
    

    问题是这个例子对 I ,因为任务是从 eval 进入外部范围。我四处寻找能够创建新范围/工作区的东西,但是 evalin save / load ,但没有得到任何进展,但也许我只是想得不够努力。

    doctest__system__* 忍受命名空间问题。。。除非你有别的想法 避免变量名冲突的策略

    1 回复  |  直到 14 年前
        1
  •  4
  •   Amro    14 年前

    一个非常有趣的项目。。我认为最好的选择是编写一个单独的函数来执行测试,并为函数中的所有变量使用唯一的前缀,以避免名称冲突。我的尝试是:

    function [PREFIX_b varargout] = testContext(PREFIX_src, PREFIX_srcOutput)
        %# TESTCONTEXT   Executes the source code and tests for
        %#               equality against the expected output
        %#
        %#   Input:
        %#       PREFIX_src       - source to execute, cellarry of statements
        %#       PREFIX_srcOutput - output to expect, cellarray of output of each statement
        %#
        %#   Output:
        %#       PREFIX_b         - true/false for success/failure of test
        %#                          note that the output is strtrim()'ed then strcmp()'ed
        %#       varargout{1}     - variable names assigned in this confined context
        %#       varargout{2}     - variable values assigned
        %#
        %#   Example 1:
        %#       source = { 'I = 5+33;' 'I' };
        %#       output = { [], ['I =' char(10) '    38'] };
        %#       b = testContext(source, output);
        %#
        %#   Example 2:
        %#       source = { 'I = 5+33; J = 2;' 'K = 1;' 'disp(I+J+K)' };
        %#       output = { [], [], '41' };
        %#       [b varNames varValues] = testContext(source, output);
        %#
        %#   See also: eval evalc
        %#
    
        PREFIX_b = true;
    
        try
            %# for each statement
            for PREFIX_i=1:numel(PREFIX_src)
                %# evaluate
                PREFIX_output = evalc( PREFIX_src{PREFIX_i} );
                PREFIX_output = strtrim(PREFIX_output);            %# trim whitespaces
                %# compare output
                if ~isempty( PREFIX_srcOutput{PREFIX_i} )
                    if ~strcmp(PREFIX_output,PREFIX_srcOutput{PREFIX_i})
                        PREFIX_b = false;
                        return
                    end
                end
            end
    
            if nargout > 1
                %# list created variables in this context
                %#clear ans
                PREFIX_vars = whos('-regexp', '^(?!PREFIX_).*');   %# java regex negative lookahead
                varargout{1} = { PREFIX_vars.name };
    
                if nargout > 2
                    %# return those variables
                    varargout{2} = cell(1,numel(PREFIX_vars));
                    for PREFIX_i=1:numel(PREFIX_vars)
                        [~,varargout{2}{PREFIX_i}] = evalc( PREFIX_vars(PREFIX_i).name );
                    end
                end
            end
    
        catch ME
            warning(ME.identifier, ME.message)
            PREFIX_b = false;
            varargout{1} = {};
            varargout{2} = {};
        end
    end
    

    我假设您能够解析m文件以恢复要测试的示例,其中您有每条语句及其预期输出。

    例如,考虑嵌入函数头中的这个简单测试:

    I = 5 + 33;
    J = 2*I;
    disp(I+J)
    

    因为只有最后一条语句有输出,所以我们将其测试为:

    source = {'I = 5 + 33;' 'J = 2*I;' 'disp(I+J)'};
    output = {[], [], '114'};
    [b varNames varValues] = testContext(source, output)
    

    结果是:

    b =
         1
    varNames = 
        'I'    'J'
    varValues = 
        [38]    [76]
    

    它显示测试是否通过或失败。或者,函数返回在该上下文中创建的变量列表及其值。