changeset 383:d18843ff4dfd

Rewrite the test suite to run Octave-style built-in tests * Makefile.am (M_FILES): New declaration. (TST_FILES): New derived declaration. (%.cc-tst): New rule to generate test scripts from compiled sources. (check-local): Call __py_tests__.m script file to run test suite. (CLEANFILES): Include fntests.log and *-tst. * __py_tests__.m: New script file to run built-in tests. * .hgignore: Include fntests.log and *.cc-tst.
author Mike Miller <mtmiller@octave.org>
date Sun, 02 Apr 2017 11:20:53 -0700
parents d36f06f07082
children c6e93e7dcfba
files .hgignore Makefile.am __py_tests__.m
diffstat 3 files changed, 195 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Sun Apr 02 10:06:42 2017 -0700
+++ b/.hgignore	Sun Apr 02 11:20:53 2017 -0700
@@ -46,6 +46,9 @@
 (^|/)PKG_(ADD|DEL)
 (^|/)octave-workspace
 
+(^|/)fntests\.log$
+(^|/).*\.cc-tst$
+
 # e.g. doc/faq/OctaveFAQ.info
 #      doc/interpreter/octave.info-4
 ^doc/.*\.info(-\d)?$
--- a/Makefile.am	Sun Apr 02 10:06:42 2017 -0700
+++ b/Makefile.am	Sun Apr 02 11:20:53 2017 -0700
@@ -39,6 +39,22 @@
   INSTALL.md \
   README.md
 
+M_FILES = \
+  @py/py.m \
+  @py/subsref.m \
+  @pyobject/cell.m \
+  @pyobject/char.m \
+  @pyobject/display.m \
+  @pyobject/dummy.m \
+  @pyobject/fieldnames.m \
+  @pyobject/methods.m \
+  @pyobject/pyobject.m \
+  @pyobject/subsasgn.m \
+  @pyobject/subsref.m \
+  __py_tests__.m \
+  pyargs.m \
+  pyversion.m
+
 OCT_FILES = \
   __py_struct_from_dict__.oct \
   pycall.oct \
@@ -63,6 +79,8 @@
   test/exceptions.py \
   test/test.py
 
+TST_FILES = $(addsuffix -tst,$(OCT_SOURCE_FILES))
+
 EXTRA_DIST = $(DOC_FILES) $(OCT_SOURCE_FILES) $(PY_FILES)
 
 EXTRA_libdir = $(PYTAVE_MODULE_INSTALL_PATH)
@@ -77,7 +95,7 @@
 libpytave_la_CPPFLAGS = $(AM_CPPFLAGS)
 libpytave_la_SOURCES = $(COMMON_SOURCE_FILES) $(PYTAVE_HEADER_FILES)
 
-CLEANFILES = *.oct PKG_ADD PKG_DEL
+CLEANFILES = *.oct *-tst PKG_ADD PKG_DEL fntests.log
 SUFFIXES = .oct
 
 AM_V_MKOCTFILE = $(am__v_MKOCTFILE_$(V))
@@ -93,6 +111,13 @@
 %.oct: %.cc libpytave.la $(PYTAVE_HEADER_FILES)
 	$(AM_V_MKOCTFILE)$(OCT_LINK) $< $(OCT_LIBS)
 
+%.cc-tst: %.cc
+	$(AM_V_GEN)rm -f $@-t $@ && \
+	( echo "## DO NOT EDIT!  Generated automatically from $(<F) by Make."; \
+	  $(GREP) '^%!' $< \
+	) > $@-t && \
+	mv $@-t $@
+
 PKG_ADD: $(OCT_SOURCE_FILES)
 	$(AM_V_GEN)for f in $(OCT_SOURCE_FILES); do \
 	  b=$${f%.cc}; \
@@ -127,6 +152,5 @@
 	@echo "    PYTHONPATH=\"\$$(pwd)/.libs:\$$(pwd)/package\" python"
 	@echo ""
 
-check-local:
-	PYTHONPATH="$(abs_srcdir)/package:$$(pwd)/package:$$(pwd)/.libs" $(PYTHON) $(srcdir)/test/exceptions.py
-	PYTHONPATH="$(abs_srcdir)/package:$$(pwd)/package:$$(pwd)/.libs" $(PYTHON) $(srcdir)/test/test.py
+check-local: $(M_FILES) $(TST_FILES)
+	octave-cli --path="$(abs_builddir)" --path="$(abs_srcdir)" __py_tests__.m $(M_FILES) $(TST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/__py_tests__.m	Sun Apr 02 11:20:53 2017 -0700
@@ -0,0 +1,164 @@
+## Copyright (C) 2017 Mike Miller
+## Copyright (C) 2005-2017 David Bateman
+##
+## This file is part of Pytave.
+##
+## Pytave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## Pytave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Pytave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## This is a script file, derived from Octave's __run_test_suite__.m
+true;
+
+function retval = __run_py_tests__ (varargin)
+
+  files_with_no_tests = {};
+  files_with_tests = {};
+
+  pso = page_screen_output ();
+
+  logfile = make_absolute_filename ("fntests.log");
+  unwind_protect
+    page_screen_output (false);
+    try
+      fid = fopen (logfile, "wt");
+      if (fid < 0)
+        error ("__run_test_suite__: could not open %s for writing", logfile);
+      endif
+      test ("", "explain", fid);
+      dp = dn = dxf = dsk = drtsk = 0;
+      puts ("\nIntegrated test scripts:\n\n");
+      for i = 1:length (varargin)
+        f = varargin{i};
+        if (has_tests (f))
+          print_test_file_name (f);
+          [p, n, xf, sk, rtsk] = test (f, "quiet", fid);
+          print_pass_fail (p, n, xf, sk, rtsk);
+          dp += p;
+          dn += n;
+          dxf += xf;
+          dsk += sk;
+          drtsk += rtsk;
+          files_with_tests(end+1) = f;
+        else
+          ## To reduce the list length, only mark .cc files that contain
+          ## DEFUN definitions.
+          files_with_no_tests(end+1) = f;
+        endif
+      endfor
+
+      puts ("\nSummary:\n\n");
+      nfail = dn - dp - dxf;
+      printf ("  PASS                         %6d\n", dp);
+      printf ("  FAIL                         %6d\n", nfail);
+      if (dxf > 0)
+        printf ("  XFAIL                        %6d\n", dxf);
+      endif
+      if (dsk > 0)
+        printf ("  SKIPPED (feature)            %6d\n", dsk);
+      endif
+      if (drtsk > 0)
+        printf ("  SKIPPED (run-time condition) %6d\n", drtsk);
+      endif
+      puts ("\n");
+      printf ("See the file %s for additional details.\n", logfile);
+      if (dxf > 0)
+        puts ("\n");
+        puts ("Items listed as XFAIL above are known bugs.\n");
+        puts ("Bug report numbers for them may be found in the log file:\n");
+        puts (logfile);
+        puts ("\nPlease help improve Pytave by contributing fixes for them.\n");
+      endif
+      if (dsk > 0 || drtsk > 0)
+        puts ("\n");
+        puts ("Tests are most often skipped because the features they require\n");
+        puts ("have been disabled.  Features are most often disabled because\n");
+        puts ("they require dependencies that were not present when Octave or\n");
+        puts ("Pytave was built.\n");
+      endif
+
+      report_files_with_no_tests (files_with_tests, files_with_no_tests, ".m");
+
+      puts ("\nPlease help improve Pytave by contributing tests for these files\n");
+      printf ("(see the list in the file %s).\n\n", logfile);
+
+      fprintf (fid, "\nFiles with no tests:\n\n%s",
+                    list_in_columns (files_with_no_tests, 80));
+      fclose (fid);
+    catch
+      disp (lasterr ());
+    end_try_catch
+  unwind_protect_cleanup
+    page_screen_output (pso);
+  end_unwind_protect
+  retval = (nfail != 0);
+endfunction
+
+function print_test_file_name (nm)
+  filler = repmat (".", 1, 60-length (nm));
+  printf ("  %s %s", nm, filler);
+endfunction
+
+function print_pass_fail (p, n, xf, sk, rtsk)
+
+  if ((n + sk + rtsk) > 0)
+    printf (" PASS   %4d/%-4d", p, n);
+    nfail = n - p - xf;
+    if (nfail > 0)
+      printf ("\n%71s %3d", "FAIL ", nfail);
+    endif
+    if (sk > 0)
+      printf ("\n%71s %3d", "(missing feature) SKIP ", sk);
+    endif
+    if (rtsk > 0)
+      printf ("\n%71s %3d", "(run-time condition) SKIP ", rtsk);
+    endif
+    if (xf > 0)
+      printf ("\n%71s %3d", "XFAIL", xf);
+    endif
+  endif
+  puts ("\n");
+
+endfunction
+
+function retval = has_tests (f)
+
+  fid = fopen (f);
+  if (fid < 0)
+    error ("__run_test_suite__: fopen failed: %s", f);
+  endif
+
+  str = fread (fid, "*char")';
+  fclose (fid);
+  retval = ! isempty (regexp (str,
+                              '^%!(assert|error|fail|test|xtest|warning)',
+                              'lineanchors', 'once'));
+
+endfunction
+
+function n = num_elts_matching_pattern (lst, pat)
+  n = sum (! cellfun ("isempty", regexp (lst, pat, 'once')));
+endfunction
+
+function report_files_with_no_tests (with, without, typ)
+  pat = ['\' typ "$"];
+  n_with = num_elts_matching_pattern (with, pat);
+  n_without = num_elts_matching_pattern (without, pat);
+  n_tot = n_with + n_without;
+  printf ("\n%d (of %d) %s files have no tests.\n", n_without, n_tot, typ);
+endfunction
+
+exit (__run_py_tests__ (argv (){:}));
+
+## Mark this file as fully tested.
+%!assert (1)