diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 08d92bf..e8913a9 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -102,3 +102,25 @@ jobs: with: paths: javascript-tap/results/**/*.tap if: always() + + # This runs Python tests using the Pytest test framework + pytest-junit: + name: Python / pytest + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.x' + - name: Install dependencies + run: pip install pytest + - name: Run test + run: pytest --junit-xml=results/pytest-junit.xml + working-directory: pytest-junit + - name: Create test summary + uses: test-summary/action@v1 + with: + paths: pytest-junit/results/*.xml + if: always() diff --git a/pytest-junit/README.md b/pytest-junit/README.md new file mode 100644 index 0000000..6a227d4 --- /dev/null +++ b/pytest-junit/README.md @@ -0,0 +1,38 @@ +test-summary example: Python with pytest +======================================== + +This produces a test summary for a Python project using the Pytest test framework. + +GitHub Actions Workflow +----------------------- + +An example GitHub Actions workflow that builds a Python project, runs the tests, runs the test-summary action and uploads the test summary markdown as an artifact. + +```yaml +name: Build and Test Python + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + workflow_dispatch: + +jobs: + build: + name: Build and Test + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@v3 + - name: Build and test + run: | + npm ci + npm run test + - name: Create test summary + uses: test-summary/action@dist + with: + paths: results/**/*.xml + if: always() +``` diff --git a/pytest-junit/directory/__init__.py b/pytest-junit/directory/__init__.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/pytest-junit/directory/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/pytest-junit/directory/test_file_2.py b/pytest-junit/directory/test_file_2.py new file mode 100644 index 0000000..e5bb196 --- /dev/null +++ b/pytest-junit/directory/test_file_2.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + + +def test_success(): + assert True diff --git a/pytest-junit/directory/test_func.py b/pytest-junit/directory/test_func.py new file mode 100644 index 0000000..e5bb196 --- /dev/null +++ b/pytest-junit/directory/test_func.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + + +def test_success(): + assert True diff --git a/pytest-junit/pytest.ini b/pytest-junit/pytest.ini new file mode 100644 index 0000000..e69de29 diff --git a/pytest-junit/test.py b/pytest-junit/test.py new file mode 100644 index 0000000..79f98a2 --- /dev/null +++ b/pytest-junit/test.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +print("hello world") diff --git a/pytest-junit/test_class.py b/pytest-junit/test_class.py new file mode 100644 index 0000000..497c288 --- /dev/null +++ b/pytest-junit/test_class.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- + + +class TestClassPassing(object): + def setup_method(self, method): + pass + + def teardown_method(self, method): + pass + + def test_passing(self): + assert True + + +class TestClassFailing(object): + def setup_method(self, method): + pass + + def teardown_method(self, method): + pass + + def test_failing(self): + assert False + + +class TestClassError(object): + def setup_method(self, method): + pass + + def teardown_method(self, method): + pass + + def test_error(self): + 1 / 0 + + +class TestClassFailingAndErrorTeardown(object): + def setup_method(self, method): + pass + + def teardown_method(self, method): + 1 / 0 + + def test_error(self): + assert False + + +class TestClassErrorSetup(object): + def setup_method(self, method): + 1 / 0 + + def teardown_method(self, method): + pass + + def test_passing(self): + assert True + + +class TestClassErrorSetupAndTeardown(object): + def setup_method(self, method): + 1 / 0 + + def teardown_method(self, method): + 1 / 0 + + def test_passing(self): + assert True + + +class TestClassErrorTeardown(object): + def setup_method(self, method): + pass + + def teardown_method(self, method): + 1 / 0 + + def test_passing(self): + assert True diff --git a/pytest-junit/test_func.py b/pytest-junit/test_func.py new file mode 100644 index 0000000..a13e07e --- /dev/null +++ b/pytest-junit/test_func.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- + +import pytest + + +def test_success(): + assert True + + +def test_fails(): + assert False + + +@pytest.mark.parametrize("number", list(range(3))) +def test_fixtures(number): + assert number % 2 == 0 + + +def test_error(): + 1 / 0 diff --git a/pytest-junit/test_module_setup_teardown.py b/pytest-junit/test_module_setup_teardown.py new file mode 100644 index 0000000..c2f474d --- /dev/null +++ b/pytest-junit/test_module_setup_teardown.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + + +def setup_module(module): + pass + + +def teardown_module(module): + print("TD MO") + + +def test_passing(): + assert True + + +def test_failing(): + assert False + + +class TestClassPassing(object): + def setup_method(self, method): + pass + + def teardown_method(self, method): + pass + + def test_passing(self): + assert True + + +class TestClassFailing(object): + def setup_method(self, method): + pass + + def teardown_method(self, method): + print("TD M") + + def test_failing(self): + assert False diff --git a/pytest-junit/test_skip.py b/pytest-junit/test_skip.py new file mode 100644 index 0000000..d1869b1 --- /dev/null +++ b/pytest-junit/test_skip.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +import pytest + + +@pytest.mark.skip(reason="Skip") +def test_skip_function(): + pass + + +class TestSkipCall(object): + @pytest.mark.skip(reason="Skip") + def test_skip_method(self): + pass + + +@pytest.mark.skip(reason="Skip") +class TestSkipClass(object): + def test_skipped_1(self): + pass + + def test_skipped_2(self): + pass diff --git a/pytest-junit/test_slow.py b/pytest-junit/test_slow.py new file mode 100644 index 0000000..ace6249 --- /dev/null +++ b/pytest-junit/test_slow.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- + +import time + + +def test_slow_passing(): + time.sleep(2) + + assert True diff --git a/pytest-junit/test_std.py b/pytest-junit/test_std.py new file mode 100644 index 0000000..aba2fdd --- /dev/null +++ b/pytest-junit/test_std.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- + +import sys + + +def test_stdout(): + print("STDOUT") + + +def test_stderr(): + sys.stderr.write("STDERR\n") + + +class TestClassStdout(object): + def setup_method(self, method): + pass + + def teardown_method(self, method): + pass + + def test_stdout(self): + print("STDOUT") + + +class TestClassStdoutSetup(object): + def setup_method(self, method): + print("SETUP") + + def teardown_method(self, method): + pass + + def test_stdout(self): + pass + + +class TestClassStdoutAllPhases(object): + def setup_method(self, method): + print("SETUP") + + def teardown_method(self, method): + print("TEARDOWN") + + def test_stdout(self): + print("TEST") + + +class TestClassFailing(object): + def setup_method(self, method): + pass + + def teardown_method(self, method): + pass + + def test_stderr(self): + sys.stderr.write("STDERR\n") diff --git a/pytest-junit/test_unittest.py b/pytest-junit/test_unittest.py new file mode 100644 index 0000000..fe72ac3 --- /dev/null +++ b/pytest-junit/test_unittest.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +import unittest + + +class TestStringMethods(unittest.TestCase): + def test_upper(self): + self.assertEqual("foo".upper(), "FOO") + + def test_isupper(self): + self.assertTrue("FOO".isupper()) + self.assertTrue("Foo".isupper()) + + +if __name__ == "__main__": + unittest.main()