diff --git a/.travis.sh b/.travis.sh index b48a58e3..94b67cb0 100644 --- a/.travis.sh +++ b/.travis.sh @@ -70,8 +70,6 @@ build_package() { check_package() ( set -ex - # we don't have test_that tests yet. - Rscript -e 'devtools::test(reporter="check")' R CMD check "$PKG_TARBALL" --as-cran ! grep -q 'WARNING' "$CHECK_LOG" # .. because ': ' was resulting in an replacement by travis and an error @@ -91,5 +89,5 @@ test_kernel() ( R CMD INSTALL "$PKG_TARBALL" Rscript -e 'IRkernel::installspec()' Rscript -e 'IRkernel::installspec(name = "testir", displayname = "testir")' - python -W ignore::DeprecationWarning test_ir.py + Rscript -e 'devtools::test()' ) diff --git a/DESCRIPTION b/DESCRIPTION index e7c7a717..1313eee5 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -25,8 +25,7 @@ Imports: jsonlite (>= 0.9.6), uuid, digest -Remotes: - IRKernel/IRdisplay, +Remotes: IRKernel/IRdisplay, Collate: 'logging.r' 'comm_manager.r' diff --git a/IRkernel.Rproj b/IRkernel.Rproj index 828602dd..452b7750 100644 --- a/IRkernel.Rproj +++ b/IRkernel.Rproj @@ -12,6 +12,8 @@ Encoding: UTF-8 RnwWeave: Sweave LaTeX: pdfLaTeX +AutoAppendNewline: Yes + BuildType: Package PackageUseDevtools: Yes PackageInstallArgs: --no-multiarch --with-keep.source diff --git a/test_ir.py b/tests/testthat/test_ir.py similarity index 95% rename from test_ir.py rename to tests/testthat/test_ir.py index d892ccd3..8feb6b15 100644 --- a/test_ir.py +++ b/tests/testthat/test_ir.py @@ -9,6 +9,7 @@ {} options(jupyter.rich_display = TRUE) ''' +#this will not work! #withr::with_options(list(jupyter.rich_display = FALSE), {}) @@ -63,6 +64,7 @@ def _execute_code(self, code, tests=True): ] def test_display_vector(self): + """display of vectors""" code = '1:3' reply, output_msgs = self._execute_code(code) @@ -78,6 +80,7 @@ def test_display_vector(self): self.assertIn('text/markdown', output_msgs[0]['content']['data']) def test_display_vector_only_plaintext(self): + """display of plain text vectors""" code = without_rich_display.format('1:3') reply, output_msgs = self._execute_code(code) data = output_msgs[0]['content']['data'] @@ -85,6 +88,7 @@ def test_display_vector_only_plaintext(self): self.assertEqual(data['text/plain'], '[1] 1 2 3') def test_irkernel_plots(self): + """plotting""" code = 'plot(1:3)' reply, output_msgs = self._execute_code(code) @@ -102,6 +106,7 @@ def test_irkernel_plots(self): self.assertEqual(metadata['image/svg+xml']['isolated'], True) def test_irkernel_plots_only_PNG(self): + """plotting PNG""" # the reset needs to happen in another execute because plots are sent after either # the next plot is opened or everything is executed, not at the time when plot # command is actually happening. @@ -123,6 +128,7 @@ def test_irkernel_plots_only_PNG(self): reply, output_msgs = self._execute_code(code, tests=False) def test_irkernel_df_default_rich_output(self): + """data.frame rich representation""" code = 'data.frame(x = 1:3)' reply, output_msgs = self._execute_code(code) @@ -131,6 +137,7 @@ def test_irkernel_df_default_rich_output(self): self.assertEqual(len(data), 3, data.keys()) def test_irkernel_df_no_rich_output(self): + """data.frame plain representation""" code = ''' options(jupyter.rich_display = FALSE) data.frame(x = 1:3) @@ -143,6 +150,7 @@ def test_irkernel_df_no_rich_output(self): self.assertEqual(len(data), 1, data.keys()) def test_html_isolated(self): + """HTML isolation""" code = ''' repr_html.full_page <- function(obj) sprintf('%s', obj) structure(0, class = 'full_page') @@ -159,6 +167,7 @@ def test_html_isolated(self): self.assertEqual(metadata['text/html']['isolated'], True) def test_in_kernel_set(self): + """jupyter.in_kernel option""" reply, output_msgs = self._execute_code('getOption("jupyter.in_kernel")') data = output_msgs[0]['content']['data'] self.assertGreaterEqual(len(data), 1, data.keys()) diff --git a/tests/testthat/test_kernel.r b/tests/testthat/test_kernel.r new file mode 100644 index 00000000..c2c0c614 --- /dev/null +++ b/tests/testthat/test_kernel.r @@ -0,0 +1,29 @@ +context('kernel') + +test_con <- pipe('python3 test_runner.py', 'rb', 'utf-8') +if (!isOpen(test_con)) open(test_con) + +while(isOpen(test_con)) { + test_result <- readBin(test_con, 'character', 1L) + if (length(test_result) == 0) break + + parts <- strsplit(test_result, '\n')[[1]] + if (length(parts) < 2) { + test_that('test output parsing', fail(sprintf('needs 2 parts, but only has one: %s', dQuote(parts)))) + next + } + + name <- parts[[1]] + status <- parts[[2]] + msg <- paste(parts[-(1:2)], collapse = '\n') + + if (nchar(msg) == 0) + msg <- status + + test_that(name, switch( + status, + ok =, 'expected failure' = succeed('Success!'), + failure =, error =, 'unexpected success' = fail(msg), + skipped = skip(msg), + stop('unknown status: ', status))) +} diff --git a/tests/testthat/test_runner.py b/tests/testthat/test_runner.py new file mode 100644 index 00000000..8ad27a29 --- /dev/null +++ b/tests/testthat/test_runner.py @@ -0,0 +1,60 @@ +import sys +import os +import re +import unittest +from warnings import simplefilter +from traceback import print_tb + + +class InlineTestResult(unittest.result.TestResult): + def getDescription(self, test): + name = re.match('.*[.]test_(\w+)', test.id()).group(1).replace('_', ' ') + return test.shortDescription() or name + + def startTest(self, test): + super().startTest(test) + print(self.getDescription(test)) + + def stopTest(self, test): + super().stopTest(test) + print(end='\0') + sys.stdout.flush() + + def addSuccess(self, test): + super().addSuccess(test) + print('ok') + + def addError(self, test, err): + super().addError(test, err) + print('error') + self.print_err(*err) + + def addFailure(self, test, err): + super().addFailure(test, err) + print('failure') + self.print_err(*err) + + def print_err(self, cls, error, tb): + print(error) + print('Traceback:') + print_tb(tb, file=sys.stdout) + + def addSkip(self, test, reason): + super().addSkip(test, reason) + print('skipped') + + def addExpectedFailure(self, test, err): + super().addExpectedFailure(test, err) + print('expected failure') + + def addUnexpectedSuccess(self, test): + super().addUnexpectedSuccess(test) + print('unexpected success') + + def printErrors(self): + pass + + +if __name__ == '__main__': + simplefilter(action='ignore', category=DeprecationWarning) + unittest.main('test_ir', testRunner=unittest.TextTestRunner(resultclass=InlineTestResult, stream=open(os.devnull, 'w')))