Repository: pfnet/pytorch-pfn-extras

Issue:
Add test for `LogWriterSaveFunc`
Add tests check if the output of `LogWriterSaveFunc` follows the specified format.


Discussion:

Resolving patch:
diff --git a/pytorch_pfn_extras/training/extensions/log_report.py b/pytorch_pfn_extras/training/extensions/log_report.py
--- a/pytorch_pfn_extras/training/extensions/log_report.py
+++ b/pytorch_pfn_extras/training/extensions/log_report.py
@@ -26,8 +26,9 @@ def __call__(self, target, file_o):
             log = json.dumps(target, indent=4)
         elif self._format == 'json-lines':
             if self._append:
-                target = target[-1]
-            log = '\n'.join([json.dumps(x) for x in target])
+                target = [target[-1]]
+            # Add a new line at the end for subsequent appends
+            log = '\n'.join([json.dumps(x) for x in target]) + '\n'
         elif self._format == 'yaml':
             if self._append:
                 target = [target[-1]]


Test patch:
diff --git a/tests/pytorch_pfn_extras_tests/training_tests/extensions_tests/test_log_report.py b/tests/pytorch_pfn_extras_tests/training_tests/extensions_tests/test_log_report.py
new file mode 100644
--- /dev/null
+++ b/tests/pytorch_pfn_extras_tests/training_tests/extensions_tests/test_log_report.py
@@ -0,0 +1,65 @@
+import json
+import os.path
+import tempfile
+
+import pytest
+import yaml
+
+import pytorch_pfn_extras as ppe
+from pytorch_pfn_extras.training import extensions
+
+
+@pytest.mark.parametrize(
+    'filename,expected_format',
+    [
+        ('out.json', 'json'),
+        ('out.xyz', 'json'),
+        (None, 'json'),
+        ('out.yaml', 'yaml'),
+        ('out.jsonl', 'json-lines'),
+    ]
+)
+def test_format_from_ext(filename, expected_format):
+    log_report = extensions.LogReport(filename=filename, format=None)
+    assert log_report._format == expected_format
+
+
+@pytest.mark.parametrize(
+    'format,append',
+    [
+        ('json', False),
+        ('json-lines', True),
+        ('json-lines', False),
+        ('yaml', True),
+        ('yaml', False),
+    ]
+)
+def test_output(format, append):
+    max_epochs = 3
+    iters_per_epoch = 5
+
+    with tempfile.TemporaryDirectory() as tmpdir:
+        manager = ppe.training.ExtensionsManager(
+            {}, {}, max_epochs=max_epochs, iters_per_epoch=iters_per_epoch,
+            out_dir=tmpdir)
+        log_report = extensions.LogReport(
+            filename='out', format=format, append=append)
+        manager.extend(log_report)
+        for epoch_idx in range(max_epochs):
+            for batch_idx in range(iters_per_epoch):
+                with manager.run_iteration():
+                    pass
+            with open(os.path.join(tmpdir, 'out')) as f:
+                data = f.read()
+                if format == 'json':
+                    values = json.loads(data)
+                elif format == 'json-lines':
+                    values = [json.loads(x) for x in data.splitlines()]
+                elif format == 'yaml':
+                    values = yaml.load(data, Loader=yaml.SafeLoader)
+                assert len(values) == epoch_idx + 1
+                this_epoch = values.pop()
+                assert this_epoch['epoch'] == epoch_idx + 1
+                assert (this_epoch['iteration']
+                        == (epoch_idx + 1) * iters_per_epoch)
+                assert 0 < this_epoch['elapsed_time']
diff --git a/tests/pytorch_pfn_extras_tests/training_tests/extensions_tests/test_print_report.py b/tests/pytorch_pfn_extras_tests/training_tests/extensions_tests/test_print_report.py
--- a/tests/pytorch_pfn_extras_tests/training_tests/extensions_tests/test_print_report.py
+++ b/tests/pytorch_pfn_extras_tests/training_tests/extensions_tests/test_print_report.py
@@ -1,29 +1,17 @@
 import io
 
-import pytest
-
 import pytorch_pfn_extras as ppe
 from pytorch_pfn_extras.training import extensions
 
 
-@pytest.mark.parametrize(
-    'format,append',
-    [
-        ('json', False),
-        ('json-lines', True),
-        ('json-lines', False),
-        ('yaml', True),
-        ('yaml', False),
-    ]
-)
-def test_run_print_report(format, append):
+def test_run_print_report():
     max_epochs = 5
     iters_per_epoch = 5
     manager = ppe.training.ExtensionsManager(
         {}, {}, max_epochs, iters_per_epoch=iters_per_epoch)
 
     out = io.StringIO()
-    log_report = extensions.LogReport(format=format, append=append)
+    log_report = extensions.LogReport()
     manager.extend(log_report)
     extension = extensions.PrintReport(out=out)
     manager.extend(extension)
@@ -33,7 +21,3 @@ def test_run_print_report(format, append):
             with manager.run_iteration():
                 pass
         assert "epoch       elapsed_time" in out.getvalue()
-
-
-if __name__ == '__main__':
-    pytest.main([__file__, '-v', '-s'])