diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 00000000..3834c598 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,11 @@ +# # This test directory for testing to simulate a Python library project structure. + +[run] +parallel = True +relative_files = True +source=./test_gh_workflow + +omit = + */__init__.py + +#ignore_errors = True diff --git a/.github/workflows/organize_all_testing_coverage_reports_with_different_os_and_py_version.yaml b/.github/workflows/organize_all_testing_coverage_reports_with_different_os_and_py_version.yaml index 96dcad58..506004f9 100644 --- a/.github/workflows/organize_all_testing_coverage_reports_with_different_os_and_py_version.yaml +++ b/.github/workflows/organize_all_testing_coverage_reports_with_different_os_and_py_version.yaml @@ -24,12 +24,13 @@ on: type: string generate_xml_report_finally: description: "Something, it only has 1 test type currently. So it could let this option to be 'true' than it would generate XML report finally to let uploading process to use it directly." - required: true type: boolean + required: false + default: false jobs: - organize_and_generate_test_report: + organize_test_reports: runs-on: ubuntu-latest steps: - name: Checkout @@ -39,7 +40,7 @@ jobs: uses: actions/download-artifact@v3 with: name: coverage - path: .coverage.${{ inputs.test_type }}* + path: ./ - name: Setup Python 3.10 in Ubuntu OS uses: actions/setup-python@v2 @@ -58,26 +59,53 @@ jobs: - name: Report testing coverage of project code run: coverage report -m + - name: Upload testing coverage report + uses: actions/upload-artifact@v3 + with: + name: project_testing_coverage_report_${{ inputs.test_type }} + path: .coverage + if-no-files-found: error + + generate_final_test_report: + if: ${{ inputs.generate_xml_report_finally == true }} +# if: inputs.generate_xml_report_finally == 'true' + needs: organize_test_reports + runs-on: ubuntu-latest + steps: + - name: Download code coverage result file + uses: actions/download-artifact@v3 + with: + name: project_testing_coverage_report_${{ inputs.test_type }} + path: ./ + - name: General testing coverage report as XML format - if: ${{ inputs.generate_xml_report_finally }} == 'true' run: coverage xml - - name: Rename the testing coverage report with test type - if: ${{ inputs.generate_xml_report_finally }} == 'false' - run: mv .coverage .coverage-${{ inputs.test_type }} - - name: Upload testing coverage report - if: ${{ inputs.generate_xml_report_finally }} == 'true' uses: actions/upload-artifact@v3 with: name: final_project_testing_coverage_report path: coverage.xml if-no-files-found: error + generate_test_type_report: + if: ${{ inputs.generate_xml_report_finally == false }} +# if: inputs.generate_xml_report_finally == 'false' + needs: organize_test_reports + runs-on: ubuntu-latest + steps: + - name: Download code coverage result file + uses: actions/download-artifact@v3 + with: + name: project_testing_coverage_report_${{ inputs.test_type }} + path: ./ + + - name: Rename the testing coverage report with test type + run: mv .coverage .coverage-${{ inputs.test_type }} + - name: Upload testing coverage report - if: ${{ inputs.generate_xml_report_finally }} == 'false' uses: actions/upload-artifact@v3 with: - name: project_testing_coverage_report + name: new_project_testing_coverage_report_${{ inputs.test_type }} path: .coverage-${{ inputs.test_type }} if-no-files-found: error diff --git a/.github/workflows/organize_all_testing_reports_with_different_test_type.yaml b/.github/workflows/organize_all_testing_reports_with_different_test_type.yaml index bdd51fc2..b2a84ef8 100644 --- a/.github/workflows/organize_all_testing_reports_with_different_test_type.yaml +++ b/.github/workflows/organize_all_testing_reports_with_different_test_type.yaml @@ -27,8 +27,14 @@ jobs: - name: Download code coverage result file uses: actions/download-artifact@v3 with: - name: project_testing_coverage_report - path: .coverage-* + name: new_project_testing_coverage_report_unit-test + path: ./ + + - name: Download code coverage result file + uses: actions/download-artifact@v3 + with: + name: new_project_testing_coverage_report_integration-test + path: ./ - name: Setup Python 3.10 in Ubuntu OS uses: actions/setup-python@v2 diff --git a/.github/workflows/test-reusable-workflows.yaml b/.github/workflows/test-reusable-workflows.yaml new file mode 100644 index 00000000..9531dd4d --- /dev/null +++ b/.github/workflows/test-reusable-workflows.yaml @@ -0,0 +1,120 @@ +name: github-action reusable workflows test +on: + push: + branches: + - "develop" + - "release" + - "release-**" + - "release/**" + - "master" + paths-ignore: + - ".gitcommitrules" + - ".gitignore" + - "LICENSE" + - "README.md" + pull_request: + branches: + - "develop" + - "release" + - "release-**" + - "release/**" + paths-ignore: + - ".gitcommitrules" + - ".gitignore" + - "LICENSE" + - "README.md" + +jobs: + + prep-testbed_unit-test: +# name: Prepare all unit test items + uses: ./.github/workflows/prepare_test_items.yaml + with: + shell_path: scripts/ci/get-unit-test-paths.sh + shell_arg: unix + + + prep-testbed_integration-test: +# name: Prepare all integration test items + uses: ./.github/workflows/prepare_test_items.yaml + with: + shell_path: scripts/ci/get-integration-test-paths.sh + shell_arg: unix + + + run_unit-test: +# name: Run all unit test items + needs: prep-testbed_unit-test + uses: ./.github/workflows/run_test_items_via_pytest.yaml + with: + test_type: unit-test + all_test_items_paths: ${{needs.prep-testbed_unit-test.outputs.all_test_items}} + + + run_integration-test: +# name: Run all integration test items. This testing would test the code with other resource or system to ensure the features work finely. + needs: prep-testbed_integration-test + uses: ./.github/workflows/run_test_items_via_pytest.yaml + with: + test_type: integration-test + all_test_items_paths: ${{needs.prep-testbed_integration-test.outputs.all_test_items}} + + + unit-test_codecov: +# name: Organize and generate the testing report and upload it to Codecov + needs: run_unit-test + uses: ./.github/workflows/organize_all_testing_coverage_reports_with_different_os_and_py_version.yaml + with: + test_type: unit-test + generate_xml_report_finally: false + + + integration-test_codecov: +# name: Organize and generate the testing report and upload it to Codecov + needs: run_integration-test + uses: ./.github/workflows/organize_all_testing_coverage_reports_with_different_os_and_py_version.yaml + with: + test_type: integration-test + generate_xml_report_finally: false + + + organize_all-test_codecov_and_generate_report: +# name: Organize and generate the testing report and upload it to Codecov + needs: [unit-test_codecov, integration-test_codecov] + uses: ./.github/workflows/organize_all_testing_reports_with_different_test_type.yaml + + + codecov_finish: +# name: Organize and generate the testing report and upload it to Codecov + if: github.ref_name == 'release' || github.ref_name == 'master' + needs: organize_all-test_codecov_and_generate_report + uses: ./.github/workflows/upload_test_report_to_codecov.yaml + secrets: + codecov_token: ${{ secrets.CODECOV_TOKEN }} + with: + download_path: ./ + codecov_flags: unit-test, integration-test + codecov_name: smoothcrawler-appintegration_github-actions_test # optional + + + codacy_finish: +# name: Upload test report to Codacy to analyse and record code quality + needs: [codecov_finish] + uses: ./.github/workflows/upload_code_report_to_codacy.yaml + secrets: + codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }} + with: + download_path: ./ + + +# pre-building_check: +## name: Check about it could work finely by installing the Python package with setup.py file +# needs: [codecov_finish, codacy_finish] +# uses: Chisanan232/GitHub-Action-Template-Python/.github/workflows/upload_code_report_to_codacy.yaml +# with: +# python_package_name: smoothcrawler +# test_import_package_code_1: import smoothcrawler as mr +# test_import_package_code_2: from smoothcrawler.crawler import SimpleCrawler +# test_import_package_code_3: from smoothcrawler.components.data import BaseHTTPResponseParser, BaseDataHandler +# test_python_script: ./scripts/test_crawler.py + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..7a71fa75 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# # This test directory for testing to simulate a Python library project structure. + +.DS_Store +__pycache__ +.coverage +.coverage.* +.pypirc +.pytest_cache/ +.python-version +code_source/ +coverage.xml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..b305b67a --- /dev/null +++ b/codecov.yml @@ -0,0 +1,4 @@ +# # This test directory for testing to simulate a Python library project structure. + +codecov: + token: $CODECOV_TOKEN diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000..2f66d7ab --- /dev/null +++ b/pytest.ini @@ -0,0 +1,14 @@ +# # This test directory for testing to simulate a Python library project structure. + +# pytest.ini +[pytest] +minversion = 0.1.0 + +addopts = + --cov=./test_gh_workflow + --cov-config=./.coveragerc + -r a + -v + --reruns 3 + +testpaths = diff --git a/requirements/requirements-test.txt b/requirements/requirements-test.txt new file mode 100644 index 00000000..a059ff3f --- /dev/null +++ b/requirements/requirements-test.txt @@ -0,0 +1,11 @@ +###### SmoothCrawler-AppIntegration Development (or Testing) Dependencies Requirements ###### +## For running pytest ## +pytest >= 7.0.0 +pytest-cov >= 3.0.0 +pytest-html >= 3.1.1 +pytest-rerunfailures >= 10.2 + +## For calculating code coverage ## +coverage >= 6.2 # In Python 3.6, its latest version supported is 6.2. But it supports 6.4 version in Python 3.10. +codecov >= 2.1.12 +coveralls >= 3.3.1 diff --git a/requirements/requirements.txt b/requirements/requirements.txt new file mode 100644 index 00000000..f97a1e17 --- /dev/null +++ b/requirements/requirements.txt @@ -0,0 +1,2 @@ +###### SmoothCrawler-AppIntegration Dependencies Requirements ###### +## Code - Basic ## diff --git a/scripts/ci/get-integration-test-paths.sh b/scripts/ci/get-integration-test-paths.sh new file mode 100644 index 00000000..45ab8e9c --- /dev/null +++ b/scripts/ci/get-integration-test-paths.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +set -ex +runtime_os=$1 + +declare -a base_tests + +getalltests() { + declare -a testpatharray=( $(ls -F "$1" | grep -v '/$' | grep -v '__init__.py' | grep -v 'test_config.py' | grep -v -E '^_[a-z_]{1,64}.py' | grep -v '__pycache__')) + + declare -a alltestpaths + for (( i = 0; i < ${#testpatharray[@]}; i++ )) ; do + alltestpaths[$i]=$1${testpatharray[$i]} + done + + base_tests=("${alltestpaths[@]}") +} + +base_path=test/integration_test/ + +getalltests $base_path + +dest=( "${base_tests[@]}" ) + + +if echo "$runtime_os" | grep -q "windows"; +then + printf '%s\n' "${dest[@]}" | jq -R . +elif echo "$runtime_os" | grep -q "unix"; +then + printf '%s\n' "${dest[@]}" | jq -R . | jq -cs . +else + printf 'error' | jq -R . +fi diff --git a/scripts/ci/get-unit-test-paths.sh b/scripts/ci/get-unit-test-paths.sh new file mode 100644 index 00000000..6c615137 --- /dev/null +++ b/scripts/ci/get-unit-test-paths.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +set -ex +runtime_os=$1 + +declare -a init_tests + +getalltests() { + declare -a testpatharray=( $(ls -F "$1" | grep -v '/$' | grep -v '__init__.py' | grep -v 'test_config.py' | grep -v -E '^_[a-z_]{1,64}.py' | grep -v '__pycache__')) + + declare -a alltestpaths + for (( i = 0; i < ${#testpatharray[@]}; i++ )) ; do + alltestpaths[$i]=$1${testpatharray[$i]} + done + + init_tests=("${alltestpaths[@]}") +} + +init_path=test/unit_test/ + +getalltests $init_path + +dest=( "${init_tests[@]}" ) + + +if echo "$runtime_os" | grep -q "windows"; +then + printf "${dest[@]}" | jq -R . +elif echo "$runtime_os" | grep -q "unix"; +then + printf '%s\n' "${dest[@]}" | jq -R . | jq -cs . +else + printf 'error' | jq -R . +fi diff --git a/scripts/run_pytest_in_develop.sh b/scripts/run_pytest_in_develop.sh new file mode 100644 index 00000000..0c21f47b --- /dev/null +++ b/scripts/run_pytest_in_develop.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +########################################################################################## +# +# Target: +# For develop to be more easier to run testing via *pytest*. +# +# Description: +# It does 2 things: run script for getting testing items and run the testing via tool *pytest*. +# This bash file must to receive a argument *testing_type* which is the key condition to let +# script runs unit test or integration test. +# +# Allowable argument: +# * unit-test: Get and run unit test. +# * integration-test: Get and run integration test. +# +########################################################################################## + +set -exm +testing_type=$1 +echo "⚙️ It would run the " + testing_type + " of the Python package SmoothCrawler-Cluster." + +echo "🔍 Get the testing items ... ⏳" + +if echo "$testing_type" | grep -q "unit-test"; +then + test_path=$(bash ./scripts/ci/get-unit-test-paths.sh windows | sed "s/\"//g" | sed 's/^//') +elif echo "$testing_type" | grep -q "integration-test"; +then + test_path=$(bash ./scripts/ci/get-integration-test-paths.sh windows | sed "s/\"//g" | sed 's/^//') +else + test_path='error' +fi + +if echo $test_path | grep -q "error"; +then + echo "❌ Got error when it tried to get testing items... 😱" + exit 1 +else + echo "🎉🎊🍾 Get the testing items successfully!" + echo "📄 The testing items are: " + echo $test_path + + echo "🤖⚒ It would start to run testing with Python testing framework *pytest*." + pytest $test_path +fi + diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 00000000..9730af16 --- /dev/null +++ b/test/__init__.py @@ -0,0 +1 @@ +# # This test directory for testing to simulate a Python library project structure. diff --git a/test/integration_test/__init__.py b/test/integration_test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/integration_test/sample.py b/test/integration_test/sample.py new file mode 100644 index 00000000..cac9f336 --- /dev/null +++ b/test/integration_test/sample.py @@ -0,0 +1,15 @@ +import test_gh_workflow.sample +import logging +import pytest + + +@pytest.fixture(scope="function") +def get_hello_python() -> str: + return test_gh_workflow.sample.hello_python() + + +def test_sample(get_hello_python: str) -> None: + logging.info("Start Integration test.") + assert get_hello_python == "Hello Python", "The return value should be 'Hello Python'." + logging.info("This is Integration test done.") + diff --git a/test/unit_test/__init__.py b/test/unit_test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test/unit_test/sample.py b/test/unit_test/sample.py new file mode 100644 index 00000000..8ac2a03c --- /dev/null +++ b/test/unit_test/sample.py @@ -0,0 +1,15 @@ +import test_gh_workflow.sample +import logging +import pytest + + +@pytest.fixture(scope="function") +def get_hello_python() -> str: + return test_gh_workflow.sample.hello_python() + + +def test_sample(get_hello_python: str) -> None: + logging.info("Start Unit test.") + assert get_hello_python == "Hello Python", "The return value should be 'Hello Python'." + logging.info("This is Unit test done.") + diff --git a/test_gh_workflow/__init__.py b/test_gh_workflow/__init__.py new file mode 100644 index 00000000..9730af16 --- /dev/null +++ b/test_gh_workflow/__init__.py @@ -0,0 +1 @@ +# # This test directory for testing to simulate a Python library project structure. diff --git a/test_gh_workflow/sample.py b/test_gh_workflow/sample.py new file mode 100644 index 00000000..682c3790 --- /dev/null +++ b/test_gh_workflow/sample.py @@ -0,0 +1,3 @@ + +def hello_python() -> str: + return "Hello Python"