Permalink
Please sign in to comment.
Browse files
ENH: Add minimal classdef support for MOcovMFile
Avoid prepending `mocov_line_covered` to: - `classdef`; - `properties` and `methods` section opening statements; - inside the entire `properties` section, since a limited subset of the M-file syntax is allowed.
- Loading branch information...
Showing
with
203 additions
and 10 deletions.
| @@ -0,0 +1,81 @@ | ||
| +function test_suite = test_MOcovMFile_recognizes_classdef_syntax | ||
| + initTestSuite; | ||
| +end | ||
| + | ||
| +function fullname = tempfile(filename, contents) | ||
| + tempfolder = fullfile(tempdir, 'mocov_fixtures'); | ||
| + [~, ~, ~] = mkdir(tempfolder); | ||
| + fullname = fullfile(tempfolder, filename); | ||
| + fid = fopen(fullname, 'w'); | ||
| + fprintf(fid, contents); | ||
| + fclose(fid); | ||
| +end | ||
| + | ||
| +function filename = create_classdef | ||
| + filename = tempfile('AClass.m', [ ... | ||
| + 'classdef AClass < handle\n', ... | ||
| + ' properties\n', ... | ||
| + ' aProp = 1;\n', ... | ||
| + ' end\n', ... | ||
| + ' properties (SetAccess = private, Dependent)\n', ... | ||
| + ' anotherProp;\n', ... | ||
| + ' end\n', ... | ||
| + ' methods\n', ... | ||
| + ' function self = AClass\n', ... | ||
| + ' fprintf(''hello world!'');\n', ... | ||
| + ' end\n', ... | ||
| + ' end\n', ... | ||
| + ' methods (Access = private)\n', ... | ||
| + ' function x = aMethod(self)\n', ... | ||
| + ' fprintf(''hello world!'');\n', ... | ||
| + ' end\n', ... | ||
| + ' end\n', ... | ||
| + 'end\n' ... | ||
| + ]); | ||
| +end | ||
| + | ||
| +function test_classdef_line_not_executable | ||
| + mfile = MOcovMFile(create_classdef); | ||
| + executable_lines = get_lines_executable(mfile); | ||
| + assert(~executable_lines(1), ... | ||
| + '`classdef` line is wrongly classified as executable'); | ||
| +end | ||
| + | ||
| +function test_methods_opening_section_not_executable | ||
| + mfile = MOcovMFile(create_classdef); | ||
| + | ||
| + lines = get_lines(mfile); | ||
| + executable_lines = get_lines_executable(mfile); | ||
| + method_opening = [8, 13]; | ||
| + | ||
| + for l = method_opening | ||
| + assert(~executable_lines(l), ... | ||
| + '`%s` line is wrongly classified as executable', lines{l}); | ||
| + end | ||
| +end | ||
| + | ||
| +function test_method_body_executable | ||
| + mfile = MOcovMFile(create_classdef); | ||
| + | ||
| + lines = get_lines(mfile); | ||
| + executable_lines = get_lines_executable(mfile); | ||
| + method_lines = [10, 15]; | ||
| + | ||
| + for l = method_lines | ||
| + assert(executable_lines(l), ... | ||
| + '`%s` line is wrongly classified as non-executable', lines{l}); | ||
| + end | ||
| +end | ||
| + | ||
| +function test_properties_line_not_executable | ||
| + mfile = MOcovMFile(create_classdef); | ||
| + | ||
| + lines = get_lines(mfile); | ||
| + executable_lines = get_lines_executable(mfile); | ||
| + properties_lines = [2:4, 5:7]; | ||
| + | ||
| + for l = properties_lines | ||
| + assert(~executable_lines(l), ... | ||
| + '`%s` line is wrongly classified as executable', lines{l}); | ||
| + end | ||
| +end |
| @@ -0,0 +1,68 @@ | ||
| +function test_suite = test_write_lines_with_prefix_generate_valid_classdef_files | ||
| + initTestSuite; | ||
| +end | ||
| + | ||
| +function fullname = tempfile(filename, contents) | ||
| + tempfolder = fullfile(tempdir, 'mocov_fixtures'); | ||
| + [~, ~, ~] = mkdir(tempfolder); | ||
| + fullname = fullfile(tempfolder, filename); | ||
| + fid = fopen(fullname, 'w'); | ||
| + fprintf(fid, contents); | ||
| + fclose(fid); | ||
| +end | ||
| + | ||
| +function filename = create_classdef | ||
| + filename = tempfile('AClass.m', [ ... | ||
| + 'classdef AClass < handle\n', ... | ||
| + ' properties\n', ... | ||
| + ' aProp = 1;\n', ... | ||
| + ' end\n', ... | ||
| + ' properties (SetAccess = private, Dependent)\n', ... | ||
| + ' anotherProp;\n', ... | ||
| + ' end\n', ... | ||
| + ' methods\n', ... | ||
| + ' function self = AClass\n', ... | ||
| + ' self.anotherProp = 2;\n', ... | ||
| + ' end\n', ... | ||
| + ' end\n', ... | ||
| + ' methods (Access = public)\n', ... | ||
| + ' function aMethod(self, x)\n', ... | ||
| + ' self.aProp = x;\n', ... | ||
| + ' end\n', ... | ||
| + ' end\n', ... | ||
| + 'end\n' ... | ||
| + ]); | ||
| +end | ||
| + | ||
| +function test_generate_valid_file | ||
| + originalPath = path; % setup | ||
| + cleaner = onCleanup(@() path(originalPath)); % teardown | ||
| + | ||
| + % Given: | ||
| + % `AClass.m` file with a classdef declaration | ||
| + filename = create_classdef; | ||
| + % a folder where mocov will store the decorated files | ||
| + foldername = fullfile(tempdir, 'mocov_decorated'); | ||
| + [~,~,~] = mkdir(foldername); | ||
| + decorated = fullfile(foldername, 'AClass.m'); | ||
| + % a valid decorator | ||
| + decorator = @(line_number) ... | ||
| + sprintf('fprintf(0, ''%s:%d'');', filename, line_number); | ||
| + | ||
| + | ||
| + % When: the decorated file is generated | ||
| + mfile = MOcovMFile(filename); | ||
| + write_lines_with_prefix(mfile, decorated, decorator); | ||
| + | ||
| + | ||
| + % Then: the decorated file should have a valid syntax | ||
| + % Since Octave do not have a linter, run the code to check the syntax. | ||
| + addpath(foldername); | ||
| + try | ||
| + aObject = AClass(); | ||
| + aObject.aMethod(4); | ||
| + catch | ||
| + assert(false, ['Problems when running the decorated file: `%s` ', ... | ||
| + 'please check for syntax errors.'], decorated); | ||
| + end | ||
| +end |
0 comments on commit
8715d0f