freelabz/secator

test: capture console output during tests

Opened this issue · 0 comments

It would be useful to capture the console output to test more things like:

  • Is the output as expected
  • Are the colors right
  • Are the debug statements working well

If using direct secator library calls, we can:

  • Add a capture_output bool option in config.
  • Pass it to rich console (secator/rich.py):
    import io
    from secator import CONFIG
    file = io.StringIO() if CONFIG.capture_output else None
    console = Console(file=file)
  • In unittests, we set SECATOR_CAPTURE_OUTPUT to 1 get the console output:
    class TestLibOutput(unittest.TestCase):
       def setUp(self):
          os.environ['SECATOR_CAPTURE_OUTPUT'] = '1'
          os.environ['SECATOR_OFFLINE_MODE'] = '1'
    
      def test_lib_capture(self):
         result = Vuln.lookup_cve('CVE-2022-23491')
         self.assertIn('Skip remote query for CVE-2022-23491", self.capture_output.getvalue())
    
       def test_nmap_capture(self):  # add a fixture for nmap here
          from secator.tasks import nmap
          from secator.rich import console
          results = nmap('localhost', ports=[80]).run()
          self.assertIn('Skip remote query for', console.file.getvalue())
  • [extra] We can also use rich.Console(record=True) and use console.export_text()

If using secator command calls, we can:

  • In unittests, we redirect raw stdout stream to a io.StringIO():
    class TestCLIOutput(unittest.TestCase):
       def setUp(self):
          self.captured_output = io.StringIO()
          sys.stdout = self.captured_output
      os.environ['SECATOR_DEBUG_COMPONENT'] = 'cve'
          from secator import CONFIG
          from secator.runners import Command
          self._Command = Command
    
      def tearDown(self):
          sys.stdout = sys.__stdout__
    
       def test_capture(self):
          from secator.runners import Command
          result = Vuln.lookup_cve('CVE-2022-23491')
          self.assertEqual(result, None)
          print(self.captured_output.getvalue())