Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functional smoke tests and automated testing workflow #336

Merged
merged 126 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
126 commits
Select commit Hold shift + click to select a range
f4f79b4
build out structure for initial smoke test
mitchelbaker-cisa Jul 5, 2024
6e29205
get latest created GWSBaselineConformance dir
mitchelbaker-cisa Jul 5, 2024
d0ab906
add capability to recursively check if paths are file/directory
mitchelbaker-cisa Jul 6, 2024
ddc4bfb
add helper function to determine if all outputs exist
mitchelbaker-cisa Jul 9, 2024
7fd0ee2
refactor into smoke_test_utils
mitchelbaker-cisa Jul 10, 2024
24bac6f
cleanup, add run_smoke_test workflow
mitchelbaker-cisa Jul 10, 2024
ec090e8
build out initial workflow for smoke testing scubagoggles from a wind…
mitchelbaker-cisa Jul 11, 2024
eeafdda
add workflow_dispatch
mitchelbaker-cisa Jul 25, 2024
f14076c
add pytest install
mitchelbaker-cisa Jul 25, 2024
153ab14
run test
mitchelbaker-cisa Jul 25, 2024
60a6469
change secret creds
mitchelbaker-cisa Jul 25, 2024
504baf3
change secret creds
mitchelbaker-cisa Jul 25, 2024
b2ae8de
change secret creds
mitchelbaker-cisa Jul 25, 2024
969df21
move location of cache step; add shell=True to test
mitchelbaker-cisa Jul 25, 2024
3c50a34
debug smoke_test.py
mitchelbaker-cisa Jul 25, 2024
8078e44
adjust smoke_test workflow
mitchelbaker-cisa Jul 25, 2024
e8d5a08
smoke_test workflow updates
mitchelbaker-cisa Jul 25, 2024
ff2e124
smoke_test workflow updates
mitchelbaker-cisa Jul 25, 2024
7291b9d
adjust smoke_test workflow
mitchelbaker-cisa Jul 26, 2024
765e44a
smoke_test workflow updates
mitchelbaker-cisa Jul 26, 2024
80ac820
smoke_test workflow updates
mitchelbaker-cisa Jul 26, 2024
b75045f
smoke_test workflow updates
mitchelbaker-cisa Jul 26, 2024
7eafdbd
adjust smoke_test workflow
mitchelbaker-cisa Jul 26, 2024
a46ccdf
adjust smoke_test workflow
mitchelbaker-cisa Jul 26, 2024
fa15734
adjust smoke_test workflow
mitchelbaker-cisa Jul 26, 2024
ca3c9ef
adjust smoke_test workflow
mitchelbaker-cisa Jul 26, 2024
891851a
adjust smoke_test workflow
mitchelbaker-cisa Jul 26, 2024
f33327a
adjust smoke_test workflow
mitchelbaker-cisa Jul 26, 2024
e684b10
adjust smoke_test workflow
mitchelbaker-cisa Jul 26, 2024
9b47f9d
adjust pip3 -> pip
mitchelbaker-cisa Jul 26, 2024
b234dd6
update numpy
mitchelbaker-cisa Jul 26, 2024
5891e9c
update secrets, create credentials.json for service account
mitchelbaker-cisa Jul 26, 2024
06c6bb3
add cache dependency path, not working yet; readd numpy line to preve…
mitchelbaker-cisa Jul 26, 2024
930066b
remove utf-8 encoding
mitchelbaker-cisa Jul 26, 2024
a14efa7
refactor try/catch handlers into smoke test methods; remove ProviderS…
mitchelbaker-cisa Jul 26, 2024
a2f92cf
workflow updates
mitchelbaker-cisa Jul 26, 2024
3adb447
create custom action for setting up repo and python version/cache
mitchelbaker-cisa Jul 26, 2024
7cb0034
make macos smoke test depend on windows job
mitchelbaker-cisa Jul 26, 2024
ce180dd
adjust local composite action
mitchelbaker-cisa Jul 26, 2024
18fb089
adjust workflow
mitchelbaker-cisa Jul 26, 2024
023f661
adjust workflow
mitchelbaker-cisa Jul 26, 2024
e0acf53
modify path structure for initialize-smoke-test action
mitchelbaker-cisa Jul 26, 2024
df161b6
modify path structure for initialize-smoke-test action
mitchelbaker-cisa Jul 26, 2024
d37ce10
modify path structure for initialize-smoke-test action
mitchelbaker-cisa Jul 26, 2024
ec7d0af
rename action to initialize-scubagoggles; move majority of steps out …
mitchelbaker-cisa Jul 26, 2024
047dd37
action modifications
mitchelbaker-cisa Jul 26, 2024
43f7f77
action modifications
mitchelbaker-cisa Jul 26, 2024
1bb3869
action changes
mitchelbaker-cisa Jul 26, 2024
f58f40e
create separate subactions for windows/mac setup
mitchelbaker-cisa Jul 26, 2024
6e1b298
fix location of shell property
mitchelbaker-cisa Jul 26, 2024
0ca7115
workflow adjustment
mitchelbaker-cisa Jul 26, 2024
551361c
workflow adjustment
mitchelbaker-cisa Jul 26, 2024
05d92ec
rename to setup python
mitchelbaker-cisa Jul 26, 2024
0ead797
add -y to bypass confirmation
mitchelbaker-cisa Jul 26, 2024
f615246
try removing shell from actions and keep in workflow
mitchelbaker-cisa Jul 26, 2024
9b56dc9
trigger workflow
mitchelbaker-cisa Jul 26, 2024
fb3443f
readd shell param
mitchelbaker-cisa Jul 26, 2024
5720e29
fix credentials.json for macos job
mitchelbaker-cisa Jul 26, 2024
6fe5219
test macos
mitchelbaker-cisa Jul 26, 2024
790cc5c
comment pytest in mac run so cache completes
mitchelbaker-cisa Jul 27, 2024
a646b03
see if credentials.json is created
mitchelbaker-cisa Jul 30, 2024
e387aeb
try converting workflow to matrix
mitchelbaker-cisa Jul 30, 2024
0b3ce16
try converting workflow to matrix
mitchelbaker-cisa Jul 30, 2024
fae6b73
try converting workflow to matrix
mitchelbaker-cisa Jul 30, 2024
515181d
test matrix version
mitchelbaker-cisa Jul 30, 2024
7dd6c70
lets see if refactoring into separate workflow changes things
mitchelbaker-cisa Jul 30, 2024
beefd50
retry conditionals
mitchelbaker-cisa Jul 30, 2024
c73c465
commit
mitchelbaker-cisa Jul 30, 2024
69a3a72
commit
mitchelbaker-cisa Jul 31, 2024
8e259a2
commit
mitchelbaker-cisa Jul 31, 2024
67f8366
fairly major change to structure.. should be clear on which action to…
mitchelbaker-cisa Jul 31, 2024
bc5cae6
didnt add input in macos dependencies action
mitchelbaker-cisa Jul 31, 2024
0954b5c
macos credentials.json update
mitchelbaker-cisa Jul 31, 2024
9d3fad2
macos credentials.json update
mitchelbaker-cisa Jul 31, 2024
7c6a583
macos credentials.json update
mitchelbaker-cisa Jul 31, 2024
ee41ee0
macos credentials.json update
mitchelbaker-cisa Jul 31, 2024
1a70d8a
macos credentials.json update
mitchelbaker-cisa Jul 31, 2024
c69b3bc
macos credentials.json update
mitchelbaker-cisa Jul 31, 2024
7dc0d46
macos credentials.json update
mitchelbaker-cisa Jul 31, 2024
dc76de1
macos credentials.json update
mitchelbaker-cisa Jul 31, 2024
3b065c6
macos credentials.json update
mitchelbaker-cisa Jul 31, 2024
f760278
macos credentials.json update
mitchelbaker-cisa Jul 31, 2024
fd16c0b
macos credentials.json update
mitchelbaker-cisa Jul 31, 2024
5581955
macos credentials.json update
mitchelbaker-cisa Jul 31, 2024
09c4be7
macos credentials.json update
mitchelbaker-cisa Jul 31, 2024
fe4e3e1
try different approach for creating credentials.json
mitchelbaker-cisa Jul 31, 2024
c207982
try different approach for creating credentials.json
mitchelbaker-cisa Jul 31, 2024
ec14d8b
try different approach for creating credentials.json
mitchelbaker-cisa Jul 31, 2024
8217553
try different approach for creating credentials.json
mitchelbaker-cisa Jul 31, 2024
2a86e9c
try different approach for creating credentials.json
mitchelbaker-cisa Jul 31, 2024
478842a
try different approach for creating credentials.json
mitchelbaker-cisa Jul 31, 2024
e9aaa09
try different approach for creating credentials.json
mitchelbaker-cisa Jul 31, 2024
2418916
try different approach for creating credentials.json
mitchelbaker-cisa Jul 31, 2024
57a2fb6
try different approach for creating credentials.json
mitchelbaker-cisa Jul 31, 2024
7c4fe2e
try different approach for creating credentials.json
mitchelbaker-cisa Jul 31, 2024
5ff1c85
try different approach for creating credentials.json
mitchelbaker-cisa Jul 31, 2024
269b900
switching to environment secrets.. issue is with repo secrets
mitchelbaker-cisa Jul 31, 2024
38f8501
switching to environment secrets.. issue is with repo secrets
mitchelbaker-cisa Jul 31, 2024
d818d70
switching to environment secrets.. issue is with repo secrets
mitchelbaker-cisa Jul 31, 2024
4f8c951
cleanup workflows/actions; add check for valid json; add types
mitchelbaker-cisa Jul 31, 2024
509d308
added test_scubagoggles_report pytest with selenium; testing Baseline…
mitchelbaker-cisa Aug 1, 2024
22b94b6
added test_scubagoggles_report pytest with selenium; testing Baseline…
mitchelbaker-cisa Aug 1, 2024
e183035
added test_scubagoggles_report pytest with selenium; testing Baseline…
mitchelbaker-cisa Aug 1, 2024
fecba85
added test_scubagoggles_report pytest with selenium; testing Baseline…
mitchelbaker-cisa Aug 1, 2024
86fae50
added test_scubagoggles_report pytest with selenium; testing Baseline…
mitchelbaker-cisa Aug 1, 2024
d755517
best practice improvements for how file protocol is handled before in…
mitchelbaker-cisa Aug 1, 2024
66637e0
best practice improvements for how file protocol is handled before in…
mitchelbaker-cisa Aug 1, 2024
4b216e5
test python v3.9, bug fix
mitchelbaker-cisa Aug 1, 2024
d184b69
readability improvements
mitchelbaker-cisa Aug 1, 2024
65a0582
expand selenium testing of scubagoggles reports, checks parent/indivi…
mitchelbaker-cisa Aug 1, 2024
15fcccb
refactor smoke_test.py; add run_selenium method for handling report t…
mitchelbaker-cisa Aug 1, 2024
cf3e519
conditionally uninstall numpy to see if 3.8.10 passes smoke test; som…
mitchelbaker-cisa Aug 2, 2024
a21b27b
conditionally uninstall numpy to see if 3.8.10 passes smoke test; som…
mitchelbaker-cisa Aug 2, 2024
7075862
try simplifying types to see if 3.8.10 passes
mitchelbaker-cisa Aug 2, 2024
bf18a9d
finish testing scubaresults for errors
mitchelbaker-cisa Aug 2, 2024
55a7fda
encapsulate selenium driver setup into a class
mitchelbaker-cisa Aug 2, 2024
31e644f
remove 3.8 from workflow; convert some static strings to const
mitchelbaker-cisa Aug 2, 2024
b0d57a4
improve error handling when verifying scubaresults.json
mitchelbaker-cisa Aug 5, 2024
beb2a48
start addressing pylint warnings for selenium_browser.py
mitchelbaker-cisa Aug 5, 2024
5033e8c
address pylint warnings across selenium_browser.py, smoke_test.py, sm…
mitchelbaker-cisa Aug 5, 2024
b268e26
addressing more of pylint warnings
mitchelbaker-cisa Aug 5, 2024
e9add6b
address some path issues with importing orchestrator methods
mitchelbaker-cisa Aug 5, 2024
808bf0d
move pytest.ini to root
mitchelbaker-cisa Aug 5, 2024
94e7cd1
continue to address pylint errors, most should be resolved now
mitchelbaker-cisa Aug 5, 2024
ed24be4
address final pylinter errors, add get_package_version() method in or…
mitchelbaker-cisa Aug 6, 2024
a3c7cf5
address last pylinter error
mitchelbaker-cisa Aug 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/actions/setup-dependencies-macos/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Setup Dependencies (macOS)
inputs:
operating-system:
required: true
default: "macos"
opa-version:
required: true
default: "0.60.0"
python-version:
required: true

runs:
using: "composite"
steps:
- name: Setup virtualenv
shell: bash
run: |
pip install virtualenv
virtualenv -p python .venv
source .venv/bin/activate

- name: Install dependencies
shell: bash
run: |
python -m pip install .
pip install -r requirements.txt
pip install pytest
pip install selenium
pip uninstall -y numpy
pip install numpy==1.26.4

- name: Download OPA executable
shell: bash
run: |
python download_opa.py -v ${{ inputs.opa-version }} -os ${{ inputs.operating-system }}
chmod +x opa_darwin_amd64
41 changes: 41 additions & 0 deletions .github/actions/setup-dependencies-windows/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Setup Dependencies (Windows)
inputs:
operating-system:
required: true
default: "windows"
opa-version:
required: true
default: "0.60.0"
python-version:
required: true

runs:
using: "composite"
steps:
- name: Setup virtualenv
shell: powershell
run: |
pip install virtualenv
python -m venv .venv
.venv\Scripts\activate

- name: Install dependencies
shell: powershell
run: |
python -m pip install .
pip install -r requirements.txt
pip install pytest
pip install selenium
pip uninstall -y numpy
pip install numpy==1.26.4

# Below python v3.9, a lower numpy v1.24.4 is used
#$pythonVersion = [version]${{ inputs.python-version }}
#if ($pythonVersion -ge [version]"3.8.18") {
# pip uninstall -y numpy
# pip install numpy==1.26.4
#}

- name: Download OPA executable
shell: powershell
run: python download_opa.py -v ${{ inputs.opa-version }} -os ${{ inputs.operating-system }}
2 changes: 1 addition & 1 deletion .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pylint
pip install pylint pytest selenium
- name: Analysing the code with pylint
run: |
pylint -d R0913,R0914,R0915,R1702,W0718,W0719,R0801 $(git ls-files '*.py')
67 changes: 67 additions & 0 deletions .github/workflows/run_smoke_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Run Smoke Test
on:
workflow_call:
workflow_dispatch:
pull_request:
types: [opened, reopened, synchronize]
branches:
- "main"
pull_request_review:
types: [submitted]
push:
# Uncomment when testing locally
#paths:
# - ".github/workflows/run_smoke_test.yml"
# - ".github/actions/setup-dependencies-windows/action.yml"
# - ".github/actions/setup-dependencies-macos/action.yml"
branches:
- "main"
#- "*smoke*"

jobs:
smoke-test:
strategy:
fail-fast: false
matrix:
os: [windows-latest, macos-latest]
# See https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json,
# ctrl + f and search "python-3.<minor>.<patch>-<darwin-arm64/win32/linux>" for supported versions
python-version: ["3.9", "3.12"] # "3.8 fails with numpy uninstall"
runs-on: ${{ matrix.os }}
environment: Development
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Setup Python v${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
cache-dependency-path: "requirements.txt"

- name: Setup Dependencies (Windows)
if: ${{ matrix.os == 'windows-latest' }}
uses: ./.github/actions/setup-dependencies-windows
with:
operating-system: "windows"
opa-version: "0.60.0"
python-version: ${{ matrix.python-version }}

- name: Setup Dependencies (macOS)
if: ${{ matrix.os == 'macos-latest' }}
uses: ./.github/actions/setup-dependencies-macos
with:
operating-system: "macos"
opa-version: "0.60.0"
python-version: ${{ matrix.python-version }}

- name: Setup credentials for service account
id: create-json
uses: jsdaniell/[email protected]
with:
name: "credentials.json"
json: ${{ secrets.GWS_GITHUB_AUTOMATION_CREDS }}

- name: Run ScubaGoggles and check for correct output
run: pytest -s -vvv ./Testing/Functional/SmokeTests/ --subjectemail="${{ secrets.GWS_SUBJECT_EMAIL }}" --domain="${{ secrets.GWS_DOMAIN }}"
75 changes: 75 additions & 0 deletions Testing/Functional/SmokeTests/selenium_browser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"""
selenium_browser.py declares a Browser class for use in ScubaGoggles testing.
"""

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

class Browser:
"""
The Browser class encapsulates the setup, usage, and teardown of a
Selenium WebDriver instance for automated browser interactions.
"""
def __init__(self):
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")

self.driver = webdriver.Chrome(options=chrome_options)

def get(self, url):
"""
Load a new web page in the current browser window.

Args:
url: The URL to load. Must be a fully qualified URL
"""
self.driver.get(url)

def quit(self):
"""
Quits the driver, closing every associated window.
"""
self.driver.quit()

def find_element(self, by, value):
"""
Find the first WebElement using the given method.
This method is affected by the 'implicit wait' times in force at the time and execution.
The find_element(...) invocation will return a matching row, or try again repeatedly
until the configured timeout is reached.

Args:
by: The locating mechanism to use, i.e. By.CLASS_NAME, By.TAG_NAME
value: The locator, i.e. "h1", "header"

Returns:
WebElement: The first matching element on the current page
"""
return self.driver.find_element(by, value)

def find_elements(self, by, value):
"""
Find all WebElements within the current page.
This method is affected by the 'implicit wait' times in force at the time and execution.
The find_elements(...) invocation will return as soon as there are more than 0 items in
the found collection, or will return an empty list of the timeout is reached.

Args:
by: The locating mechanism to use, i.e. By.CLASS_NAME, By.TAG_NAME
value: The locator, i.e. "h1", "header"

Returns:
WebElement: A list of all matching WebElements, or an empty list if nothing matches
"""
return self.driver.find_elements(by, value)

def current_url(self):
"""
Get a string representing the current URL that the browser is looking at.

Returns:
The URL of the page currently loaded in the browser
"""
return self.driver.current_url
72 changes: 72 additions & 0 deletions Testing/Functional/SmokeTests/smoke_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"""
smoke_test.py declares a SmokeTest class for ScubaGoggles automation testing.
"""

import subprocess
import os
import pytest
from smoke_test_utils import (
get_output_path,
prepend_file_protocol,
get_required_entries,
verify_all_outputs_exist,
verify_output_type,
run_selenium,
verify_scubaresults,
)

SAMPLE_REPORT = "sample-report"
SCUBA_RESULTS = "ScubaResults.json"
BASELINE_REPORTS = "BaselineReports.html"

class SmokeTest:
"""
Pytest class to encapsulate the following test cases:

- Generate the correct output files (BaselineReports.html, ScubaResults.json, etc)
- Check the content of html files, verify href attributes are correct, etc
- Check if ScubaResults.json contains errors in the summary. If errors exist, then
either API calls or functions produced exceptions which need to be handled
"""
def test_scubagoggles_output(self, subjectemail):
"""
Test if the `scubagoggles gws` command generates correct output for all baselines.

Args:
subjectemail: The email address of a user for the service account
"""
try:
command: str = f"scubagoggles gws --subjectemail {subjectemail} --quiet"
subprocess.run(command, shell=True, check=True)
output_path: str = get_output_path()
output: list = verify_output_type(output_path, [])
required_entries = get_required_entries(os.path.join(os.getcwd(), SAMPLE_REPORT), [])
verify_all_outputs_exist(output, required_entries)
except (OSError, ValueError, Exception) as e:
pytest.fail(f"An error occurred, {e}")

def test_scubaresults(self):
"""
Determine if ScubaResults.json contains API errors or exceptions.
"""
try:
output_path: str = get_output_path()
scubaresults_path: str = os.path.join(output_path, SCUBA_RESULTS)
with open(scubaresults_path, encoding="utf-8") as jsonfile:
verify_scubaresults(jsonfile)
except (ValueError, Exception) as e:
pytest.fail(f"An error occurred, {e}")

def test_scubagoggles_report(self, browser, domain):
"""
Test if the generated baseline reports are correct,
i.e. BaselineReports.html, CalendarReport.html, ChatReport.html
"""
try:
output_path: str = get_output_path()
report_path: str = prepend_file_protocol(os.path.join(output_path, BASELINE_REPORTS))
browser.get(report_path)
run_selenium(browser, domain)
except (ValueError, AssertionError, Exception) as e:
browser.quit()
pytest.fail(f"An error occurred, {e}")
Loading
Loading