scubagoggles 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scubagoggles/Testing/Functional/SmokeTests/README.md +142 -0
- scubagoggles/Testing/Functional/SmokeTests/requirements.txt +3 -0
- scubagoggles/Testing/Functional/SmokeTests/selenium_browser.py +81 -0
- scubagoggles/Testing/Functional/SmokeTests/smoke_test.py +82 -0
- scubagoggles/Testing/Functional/SmokeTests/smoke_test_utils.py +383 -0
- scubagoggles/Testing/Functional/conftest.py +49 -0
- scubagoggles/Testing/RegoTests/calendar/calendar_api01_test.rego +76 -0
- scubagoggles/Testing/RegoTests/calendar/calendar_api02_test.rego +49 -0
- scubagoggles/Testing/RegoTests/calendar/calendar_api03_test.rego +70 -0
- scubagoggles/Testing/RegoTests/calendar/calendar_api04_test.rego +49 -0
- scubagoggles/Testing/RegoTests/chat/chat05_test.rego +799 -0
- scubagoggles/Testing/RegoTests/chat/chat_api01_test.rego +73 -0
- scubagoggles/Testing/RegoTests/chat/chat_api02_test.rego +57 -0
- scubagoggles/Testing/RegoTests/chat/chat_api03_test.rego +82 -0
- scubagoggles/Testing/RegoTests/chat/chat_api04_test.rego +91 -0
- scubagoggles/Testing/RegoTests/classroom/classroom_api01_test.rego +90 -0
- scubagoggles/Testing/RegoTests/classroom/classroom_api02_test.rego +62 -0
- scubagoggles/Testing/RegoTests/classroom/classroom_api03_test.rego +65 -0
- scubagoggles/Testing/RegoTests/classroom/classroom_api04_test.rego +65 -0
- scubagoggles/Testing/RegoTests/classroom/classroom_api05_test.rego +65 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols02_test.rego +153 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols03_test.rego +521 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols06_test.rego +227 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols07_test.rego +25 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols09_test.rego +48 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols10_test.rego +489 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols13_test.rego +1113 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols14_test.rego +48 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols15_test.rego +335 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols17_test.rego +98 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api01_test.rego +301 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api04_test.rego +64 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api05_test.rego +160 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api08_test.rego +119 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api10_test.rego +43 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api11_test.rego +59 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api12_test.rego +125 -0
- scubagoggles/Testing/RegoTests/commoncontrols/commoncontrols_api16_test.rego +97 -0
- scubagoggles/Testing/RegoTests/drive/drive05_test.rego +248 -0
- scubagoggles/Testing/RegoTests/drive/drive_api01_test.rego +324 -0
- scubagoggles/Testing/RegoTests/drive/drive_api02_test.rego +178 -0
- scubagoggles/Testing/RegoTests/drive/drive_api03_test.rego +96 -0
- scubagoggles/Testing/RegoTests/drive/drive_api04_test.rego +72 -0
- scubagoggles/Testing/RegoTests/drive/drive_api06_test.rego +89 -0
- scubagoggles/Testing/RegoTests/gmail/gmail02_test.rego +94 -0
- scubagoggles/Testing/RegoTests/gmail/gmail03_test.rego +155 -0
- scubagoggles/Testing/RegoTests/gmail/gmail04_test.rego +402 -0
- scubagoggles/Testing/RegoTests/gmail/gmail13_test.rego +355 -0
- scubagoggles/Testing/RegoTests/gmail/gmail15_test.rego +26 -0
- scubagoggles/Testing/RegoTests/gmail/gmail16_test.rego +338 -0
- scubagoggles/Testing/RegoTests/gmail/gmail17_test.rego +24 -0
- scubagoggles/Testing/RegoTests/gmail/gmail18_test.rego +69 -0
- scubagoggles/Testing/RegoTests/gmail/gmail_api01_test.rego +73 -0
- scubagoggles/Testing/RegoTests/gmail/gmail_api05_test.rego +214 -0
- scubagoggles/Testing/RegoTests/gmail/gmail_api06_test.rego +174 -0
- scubagoggles/Testing/RegoTests/gmail/gmail_api07_test.rego +278 -0
- scubagoggles/Testing/RegoTests/gmail/gmail_api08_test.rego +46 -0
- scubagoggles/Testing/RegoTests/gmail/gmail_api09_test.rego +61 -0
- scubagoggles/Testing/RegoTests/gmail/gmail_api10_test.rego +48 -0
- scubagoggles/Testing/RegoTests/gmail/gmail_api11_test.rego +46 -0
- scubagoggles/Testing/RegoTests/gmail/gmail_api12_test.rego +48 -0
- scubagoggles/Testing/RegoTests/gmail/gmail_api14_test.rego +49 -0
- scubagoggles/Testing/RegoTests/gmail/gmail_api15_test.rego +73 -0
- scubagoggles/Testing/RegoTests/groups/groups_api01_test.rego +56 -0
- scubagoggles/Testing/RegoTests/groups/groups_api02_test.rego +56 -0
- scubagoggles/Testing/RegoTests/groups/groups_api03_test.rego +56 -0
- scubagoggles/Testing/RegoTests/groups/groups_api04_test.rego +63 -0
- scubagoggles/Testing/RegoTests/groups/groups_api05_test.rego +63 -0
- scubagoggles/Testing/RegoTests/groups/groups_api06_test.rego +49 -0
- scubagoggles/Testing/RegoTests/meet/meet05_test.rego +288 -0
- scubagoggles/Testing/RegoTests/meet/meet06_test.rego +51 -0
- scubagoggles/Testing/RegoTests/meet/meet_api01_test.rego +48 -0
- scubagoggles/Testing/RegoTests/meet/meet_api02_test.rego +48 -0
- scubagoggles/Testing/RegoTests/meet/meet_api03_test.rego +45 -0
- scubagoggles/Testing/RegoTests/meet/meet_api04_test.rego +45 -0
- scubagoggles/Testing/RegoTests/sites/sites_api01_test.rego +71 -0
- scubagoggles/Testing/run_unit_tests.py +100 -0
- scubagoggles/__init__.py +7 -0
- scubagoggles/auth.py +166 -0
- scubagoggles/baselines/README.md +11 -0
- scubagoggles/baselines/calendar.md +221 -0
- scubagoggles/baselines/chat.md +247 -0
- scubagoggles/baselines/classroom.md +223 -0
- scubagoggles/baselines/commoncontrols.md +1392 -0
- scubagoggles/baselines/drive.md +409 -0
- scubagoggles/baselines/gmail.md +1142 -0
- scubagoggles/baselines/groups.md +261 -0
- scubagoggles/baselines/images/MFA.PNG +0 -0
- scubagoggles/baselines/meet.md +287 -0
- scubagoggles/baselines/sites.md +65 -0
- scubagoggles/config.py +230 -0
- scubagoggles/getopa.py +259 -0
- scubagoggles/main.py +506 -0
- scubagoggles/orchestrator.py +600 -0
- scubagoggles/policy_api.py +883 -0
- scubagoggles/provider.py +695 -0
- scubagoggles/purge.py +132 -0
- scubagoggles/rego/Calendar.rego +235 -0
- scubagoggles/rego/Chat.rego +521 -0
- scubagoggles/rego/Classroom.rego +289 -0
- scubagoggles/rego/Commoncontrols.rego +2051 -0
- scubagoggles/rego/Drive.rego +854 -0
- scubagoggles/rego/Gmail.rego +1486 -0
- scubagoggles/rego/Groups.rego +271 -0
- scubagoggles/rego/Meet.rego +292 -0
- scubagoggles/rego/Sites.rego +43 -0
- scubagoggles/rego/Utils.rego +630 -0
- scubagoggles/reporter/FrontPageReport/FrontPageReportTemplate.html +29 -0
- scubagoggles/reporter/IndividualReport/AlertsDescriptions.json +41 -0
- scubagoggles/reporter/IndividualReport/IndividualReportTemplate.html +25 -0
- scubagoggles/reporter/__init__.py +0 -0
- scubagoggles/reporter/images/cisa_logo.png +0 -0
- scubagoggles/reporter/images/triangle-exclamation-solid.svg +1 -0
- scubagoggles/reporter/md_parser.py +409 -0
- scubagoggles/reporter/reporter.py +688 -0
- scubagoggles/reporter/scripts/main.js +71 -0
- scubagoggles/reporter/styles/FrontPageStyle.css +65 -0
- scubagoggles/reporter/styles/main.css +167 -0
- scubagoggles/robust_dns.py +216 -0
- scubagoggles/run_rego.py +193 -0
- scubagoggles/sample-report/ActionsPlan.csv +84 -0
- scubagoggles/sample-report/BaselineReports.html +305 -0
- scubagoggles/sample-report/IndividualReports/CalendarReport.html +351 -0
- scubagoggles/sample-report/IndividualReports/ChatReport.html +370 -0
- scubagoggles/sample-report/IndividualReports/ClassroomReport.html +363 -0
- scubagoggles/sample-report/IndividualReports/CommoncontrolsReport.html +976 -0
- scubagoggles/sample-report/IndividualReports/DriveReport.html +445 -0
- scubagoggles/sample-report/IndividualReports/GmailReport.html +764 -0
- scubagoggles/sample-report/IndividualReports/GroupsReport.html +375 -0
- scubagoggles/sample-report/IndividualReports/MeetReport.html +382 -0
- scubagoggles/sample-report/IndividualReports/SitesReport.html +280 -0
- scubagoggles/sample-report/IndividualReports/images/cisa_logo.png +0 -0
- scubagoggles/sample-report/IndividualReports/images/triangle-exclamation-solid.svg +1 -0
- scubagoggles/sample-report/ScubaResults_f4070c73-5faa-4f70.json +98729 -0
- scubagoggles/sample-report/TestResults.json +1189 -0
- scubagoggles/scuba_argument_parser.py +157 -0
- scubagoggles/scuba_constants.py +47 -0
- scubagoggles/user_setup.py +270 -0
- scubagoggles/utils/build.sh +199 -0
- scubagoggles/utils/checkOPAHash.sh +32 -0
- scubagoggles/utils/test_opa.sh +24 -0
- scubagoggles/utils/update_policyid_version.py +66 -0
- scubagoggles/utils.py +139 -0
- scubagoggles/version.py +448 -0
- scubagoggles-0.5.0.dist-info/METADATA +96 -0
- scubagoggles-0.5.0.dist-info/RECORD +150 -0
- scubagoggles-0.5.0.dist-info/WHEEL +5 -0
- scubagoggles-0.5.0.dist-info/entry_points.txt +2 -0
- scubagoggles-0.5.0.dist-info/licenses/LICENSE +121 -0
- scubagoggles-0.5.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# ScubaGoggles Functional Smoke Testing Automation
|
|
2
|
+
The ScubaGoggles repository consists of an automation suite to help test the functionality of the ScubaGoggles tool itself. The test automation is geared towards contributors who want to execute the functional smoke testing orchestrator as part of their development/testing activity.
|
|
3
|
+
|
|
4
|
+
This README outlines the ScubaGoggles software test automation structure and its usage. The document also contains instructions for adding new tests to the existing automation suite if necessary.
|
|
5
|
+
|
|
6
|
+
## Table of Contents
|
|
7
|
+
- [Smoke Testing Prerequisites](#smoke-testing-prerequisites)
|
|
8
|
+
- [Pytest and Selenium](#pytest-and-selenium)
|
|
9
|
+
- [Google Service Account](#google-service-account)
|
|
10
|
+
- [Functional Smoke Testing Structure](#functional-smoke-testing-structure)
|
|
11
|
+
- [Smoke Testing Classes and Methods](#smoke-testing-classes-and-methods)
|
|
12
|
+
- [Automated workflow via GitHub Actions](#automated-workflow-via-github-actions)
|
|
13
|
+
- [Functional Smoke Testing Usage](#functional-smoke-testing-usage)
|
|
14
|
+
- [Running in a Local Development Environment](#running-in-a-local-development-environment)
|
|
15
|
+
- [Running Remotely via GitHub Actions](#running-remotely-via-github-actions)
|
|
16
|
+
- [Adding New Tests](#adding-new-tests)
|
|
17
|
+
|
|
18
|
+
## Smoke Testing Prerequisites ##
|
|
19
|
+
Running the ScubaGoggles functional smoke tests requires a Windows, MacOS, or Linux computer or VM. The development environment should have Python v3.10.x installed at a minimum ([refer to our installing Python dependencies documentation if its not already installed](https://github.com/cisagov/ScubaGoggles/blob/main/docs/installation/DownloadAndInstall.md#installing-python-dependencies)), Pytest, and Selenium installed locally.
|
|
20
|
+
|
|
21
|
+
### Pytest and Selenium ###
|
|
22
|
+
Pytest is a Python testing framework which is commonly used for unit, integration, and functional testing. ([Pytest Get Started](https://docs.pytest.org/en/stable/getting-started.html))
|
|
23
|
+
|
|
24
|
+
Selenium supports automation of all the major browsers in the market through the use of WebDriver. ([Selenium Get Started](https://www.selenium.dev/documentation/webdriver/getting_started/))
|
|
25
|
+
|
|
26
|
+
To install Pytest and Selenium on your development environment, open a new terminal session and run the following command:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
pip install pytest selenium
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
> [!NOTE]
|
|
33
|
+
> The functional smoke tests use Chrome as its WebDriver when running Selenium tests. [Setup ChromeDriver](https://developer.chrome.com/docs/chromedriver/get-started) if you don't already have the Google Chrome web browser installed.
|
|
34
|
+
|
|
35
|
+
### Google Service Account ###
|
|
36
|
+
The ScubaGoggles functional smoke tests must be executed with a service account. [Refer to our service account documentation on how to get setup.](https://github.com/cisagov/ScubaGoggles/blob/main/docs/authentication/ServiceAccount.md#using-a-service-account)
|
|
37
|
+
|
|
38
|
+
A `credentials.json` file is required at the root directory of the ScubaGoggles project if running the functional smoke tests in a local development environment.
|
|
39
|
+
|
|
40
|
+
Take note of the `subjectemail`, the email used to authenticate with GWS that has necessary administrator permissions, and the GWS `customerdomain` that ScubaGoggles is run against. Both credentials are required in a later step.
|
|
41
|
+
|
|
42
|
+
## Functional Smoke Testing Structure ##
|
|
43
|
+
ScubaGoggles functional smoke testing has two main components: the smoke testing orchestrator and the automated workflow run via GitHub Actions.
|
|
44
|
+
|
|
45
|
+
### Smoke Testing Classes and Methods ###
|
|
46
|
+
The smoke testing orchestrator ([/Testing/Functional/SmokeTests/smoke_test.py](https://github.com/cisagov/ScubaGoggles/blob/main/Testing/Functional/SmokeTests/smoke_test.py)) executes each test declared inside the `SmokeTest` class. The tests currently cover:
|
|
47
|
+
- if the `scubagoggles gws` command generates valid output for all baselines
|
|
48
|
+
- if ScubaResults.json contains API errors or exceptions
|
|
49
|
+
- if the generated baseline reports, i.e. BaselineReports.html, CalendarReport.html, ChatReport.html, etc., contain valid content and all links redirect accordingly
|
|
50
|
+
|
|
51
|
+
The smoke testing utils ([/Testing/Functional/SmokeTests/smoke_test_utils.py](https://github.com/cisagov/ScubaGoggles/blob/main/Testing/Functional/SmokeTests/smoke_test_utils.py)) stores helper methods which perform various operations.
|
|
52
|
+
|
|
53
|
+
The Selenium Browser class ([/Testing/Functional/SmokeTests/selenium_browser.py](https://github.com/cisagov/ScubaGoggles/blob/main/Testing/Functional/SmokeTests/selenium_browser.py)) encapsulates the setup, usage, and teardown of Selenium WebDriver instances.
|
|
54
|
+
|
|
55
|
+
The Pytest configuration methods ([/Testing/Functional/SmokeTests/conftest.py](https://github.com/cisagov/ScubaGoggles/blob/main/Testing/Functional/conftest.py)) declare various Pytest fixtures, allowing for the use of CLI arguments when invoking the Pytest command.
|
|
56
|
+
|
|
57
|
+
### Automated Workflow via GitHub Actions ###
|
|
58
|
+
The automated workflow for running the functional smoke tests ([/.github/workflows/run_smoke_test.yml](https://github.com/cisagov/ScubaGoggles/blob/main/.github/workflows/run_smoke_test.yml)) is triggered on `push` events to the main branch, `pull_request` events when a pull request is opened/reopened/reviewed, and manually with custom user input via workflow_dispatch.
|
|
59
|
+
|
|
60
|
+
## Functional Smoke Testing Usage ##
|
|
61
|
+
After completing all of the prerequisite steps, the functional smoke tests can be run in a local development environment or remotely via GitHub Actions.
|
|
62
|
+
|
|
63
|
+
### Running in a Local Development Environment ###
|
|
64
|
+
> [!IMPORTANT]
|
|
65
|
+
> Ensure that you have correctly setup a Google service account and that the `credentials.json` stored at the root directory of the ScubaGoggles project is up to date. If you haven't already, please refer back to the [prerequisite step on Google Service Accounts](#google-service-account) for how to setup before proceeding.
|
|
66
|
+
|
|
67
|
+
The following arguments are required when running the functional smoke tests:
|
|
68
|
+
- `--subjectemail="user@domain.com"` (the email used to authenticate with GWS, must have necessary administrator permissions)
|
|
69
|
+
- `--customerdomain="domain.com"` (the domain that ScubaGoggles is run against)
|
|
70
|
+
|
|
71
|
+
Replace `user@domain.com` with your email and `domain.com` with your domain, then run the following command to execute the functional smoke tests:
|
|
72
|
+
```
|
|
73
|
+
pytest ./Testing/Functional/SmokeTests/ -vvv --subjectemail="user@domain.com" --customerdomain="domain.com"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Common Pytest parameters and their use cases:
|
|
77
|
+
- `-v` or `--verbose` (shows individual test names and results)
|
|
78
|
+
- `-vv` (increases verbosity further, shows detailed output about each test)
|
|
79
|
+
- `-vvv` (shows even more detailed output and debug-level information)
|
|
80
|
+
- `-s` (disables output capturing allowing print() statements and logs to be shown in the console)
|
|
81
|
+
- `-k` (run tests that match a keyword)
|
|
82
|
+
|
|
83
|
+
Example (only runs test_scubagoggles_output, deselects the rest):
|
|
84
|
+
```
|
|
85
|
+
pytest ./Testing/Functional/SmokeTests/ -vvv -k test_scubagoggles_output --subjectemail="user@domain.com" --customerdomain="domain.com"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- `--tb=short`, `tb=long`, or `tb=no` (provide either brief, full, or suppress the traceback output for failed tests)
|
|
89
|
+
- `-q` (reduces output to show only minimal information)
|
|
90
|
+
|
|
91
|
+
Run `pytest -h` for a full list of CLI options or [learn more about Pytest usage here.](https://docs.pytest.org/en/7.1.x/how-to/usage.html)
|
|
92
|
+
|
|
93
|
+
### Running Remotely via GitHub Actions ###
|
|
94
|
+
Go to the [run_smoke_test.yml workflow](https://github.com/cisagov/ScubaGoggles/actions/workflows/run_smoke_test.yml) in the GitHub Actions tab, then click the "Run workflow" dropdown button.
|
|
95
|
+
|
|
96
|
+
The default values are the following:
|
|
97
|
+
- ref branch: `main` but can be set to any branch
|
|
98
|
+
- operating system: `['windows-latest', 'macos-latest']` ([list of supported GitHub-hosted runners](https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories))
|
|
99
|
+
- python version: `['3.10']`
|
|
100
|
+
- opa version: "0.60.0"
|
|
101
|
+
|
|
102
|
+

|
|
103
|
+
|
|
104
|
+
Feel free to play around with the inputs then click the "Run workflow" button when ready. The workflow will create a matrix strategy for each combination. For example, passing `['windows-latest', 'macos-latest']`, `['3.10', '3.11', 3.12']`, and OPA version `0.60.0` will create the following:
|
|
105
|
+
|
|
106
|
+

|
|
107
|
+
|
|
108
|
+
Some factors to consider:
|
|
109
|
+
- Each input is required so an empty string will fail validation. `[]`, `['']`, `['', ]` may also cause the workflow to error out, although this is expected behavior.
|
|
110
|
+
- `ubuntu-latest` has not been tested as a value for operating system. Support can be added for this, although its dependent on if this is something we want to test for ScubaGoggles as a whole.
|
|
111
|
+
- Python versions <3.10.x are not supported and will cause the smoke test workflow to fail.
|
|
112
|
+
- [Due to the lack of an array input type from GitHub](https://github.com/orgs/community/discussions/11692), the required format is an array of strings for the operating system and python version inputs. This is something to capture as a future todo once arrays are available.
|
|
113
|
+
|
|
114
|
+
## Adding New Tests ##
|
|
115
|
+
A new smoke test should be added as a method in the [SmokeTest class](https://github.com/cisagov/ScubaGoggles/blob/main/Testing/Functional/SmokeTests/smoke_test.py). Helper methods should be added in [smoke_test_utils.py](https://github.com/cisagov/ScubaGoggles/blob/main/Testing/Functional/SmokeTests/smoke_test_utils.py).
|
|
116
|
+
|
|
117
|
+
Below is an example that tests the `scubagoggles gws` command:
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
class SmokeTest:
|
|
121
|
+
...
|
|
122
|
+
|
|
123
|
+
def test_scubagoggles_execution(self, subjectemail):
|
|
124
|
+
"""
|
|
125
|
+
Test if the `scubagoggles gws` command succeeds or fails.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
subjectemail: The email address of an admin user who created the service account
|
|
129
|
+
"""
|
|
130
|
+
try:
|
|
131
|
+
command: str = f"scubagoggles gws --subjectemail {subjectemail} --quiet"
|
|
132
|
+
result = subprocess.run(command, shell=True, check=True, capture_output=True)
|
|
133
|
+
|
|
134
|
+
if result.returncode != 0:
|
|
135
|
+
print(f"Scubagoggles execution failed with error:\n{result.stderr}")
|
|
136
|
+
assert False
|
|
137
|
+
else:
|
|
138
|
+
print("Scubagoggles execution succeeded")
|
|
139
|
+
print(f"Output:\n{result.stdout}")
|
|
140
|
+
except Exception as e:
|
|
141
|
+
pytest.fail(f"An error occurred, {e}")
|
|
142
|
+
```
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""
|
|
2
|
+
selenium_browser.py declares a Browser class for use in ScubaGoggles testing.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from selenium import webdriver
|
|
6
|
+
from selenium.webdriver.chrome.options import Options
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Browser:
|
|
10
|
+
"""
|
|
11
|
+
The Browser class encapsulates the setup, usage, and teardown of a
|
|
12
|
+
Selenium WebDriver instance for automated browser interactions.
|
|
13
|
+
"""
|
|
14
|
+
def __init__(self):
|
|
15
|
+
chrome_options = Options()
|
|
16
|
+
chrome_options.add_argument('--headless=new')
|
|
17
|
+
chrome_options.add_argument('--log-level=3')
|
|
18
|
+
chrome_options.add_argument('--window-size=1200,800')
|
|
19
|
+
chrome_options.add_argument('--no-sandbox')
|
|
20
|
+
chrome_options.add_argument('--disable-dev-shm-usage')
|
|
21
|
+
|
|
22
|
+
self.driver = webdriver.Chrome(options=chrome_options)
|
|
23
|
+
|
|
24
|
+
def get(self, url):
|
|
25
|
+
"""
|
|
26
|
+
Load a new web page in the current browser window.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
url: The URL to load. Must be a fully qualified URL
|
|
30
|
+
"""
|
|
31
|
+
self.driver.get(url)
|
|
32
|
+
|
|
33
|
+
def quit(self):
|
|
34
|
+
"""
|
|
35
|
+
Quits the driver, closing every associated window.
|
|
36
|
+
"""
|
|
37
|
+
self.driver.quit()
|
|
38
|
+
|
|
39
|
+
def find_element(self, by, value):
|
|
40
|
+
"""
|
|
41
|
+
Find the first WebElement using the given method. This method is
|
|
42
|
+
affected by the 'implicit wait' times in force at the time and
|
|
43
|
+
execution. The find_element(...) invocation will return a matching
|
|
44
|
+
row, or try again repeatedly until the configured timeout is reached.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
by: The locating mechanism to use, i.e. By.CLASS_NAME, By.TAG_NAME
|
|
48
|
+
value: The locator, i.e. "h1", "header"
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
WebElement: The first matching element on the current page
|
|
52
|
+
"""
|
|
53
|
+
return self.driver.find_element(by, value)
|
|
54
|
+
|
|
55
|
+
def find_elements(self, by, value):
|
|
56
|
+
"""
|
|
57
|
+
Find all WebElements within the current page. This method is affected
|
|
58
|
+
by the 'implicit wait' times in force at the time and execution. The
|
|
59
|
+
find_elements(...) invocation will return as soon as there are more
|
|
60
|
+
than 0 items in the found collection, or will return an empty list of
|
|
61
|
+
the timeout is reached.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
by: The locating mechanism to use, i.e. By.CLASS_NAME, By.TAG_NAME
|
|
65
|
+
value: The locator, i.e. "h1", "header"
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
WebElement: A list of all matching WebElements, or an empty list
|
|
69
|
+
if nothing matches
|
|
70
|
+
"""
|
|
71
|
+
return self.driver.find_elements(by, value)
|
|
72
|
+
|
|
73
|
+
def current_url(self):
|
|
74
|
+
"""
|
|
75
|
+
Get a string representing the current URL that the browser is looking
|
|
76
|
+
at.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
The URL of the page currently loaded in the browser
|
|
80
|
+
"""
|
|
81
|
+
return self.driver.current_url
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""
|
|
2
|
+
smoke_test.py declares a SmokeTest class for ScubaGoggles automation testing.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import subprocess
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from smoke_test_utils import (get_output_path,
|
|
10
|
+
get_required_entries,
|
|
11
|
+
run_selenium,
|
|
12
|
+
sample_report_dir,
|
|
13
|
+
top_report_url,
|
|
14
|
+
verify_all_outputs_exist,
|
|
15
|
+
verify_output_type,
|
|
16
|
+
verify_scubaresults)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SmokeTest:
|
|
20
|
+
"""
|
|
21
|
+
Pytest class to encapsulate the following test cases:
|
|
22
|
+
|
|
23
|
+
- Generate the correct output files (BaselineReports.html,
|
|
24
|
+
ScubaResults.json, etc)
|
|
25
|
+
- Check the content of html files, verify href attributes are
|
|
26
|
+
correct, etc
|
|
27
|
+
- Check if ScubaResults.json contains errors in the summary. If errors
|
|
28
|
+
exist, then either API calls or functions produced exceptions which
|
|
29
|
+
need to be handled
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def test_scubagoggles_output(subjectemail: str):
|
|
34
|
+
"""
|
|
35
|
+
Test if the `scubagoggles gws` command generates correct output for
|
|
36
|
+
all baselines.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
subjectemail: The email address of a user for the service account.
|
|
40
|
+
If None (or the empty string), the user's OAuth credentials are
|
|
41
|
+
used instead.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
svc_account_option = (f' --subjectemail {subjectemail}' if subjectemail
|
|
45
|
+
else '')
|
|
46
|
+
command = f'scubagoggles gws{svc_account_option} --quiet '
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
subprocess.run(command, shell=True, check=True)
|
|
50
|
+
output_path = get_output_path()
|
|
51
|
+
output: list = verify_output_type(output_path, [])
|
|
52
|
+
report_dir = sample_report_dir()
|
|
53
|
+
required_entries = get_required_entries(report_dir, [])
|
|
54
|
+
verify_all_outputs_exist(output, required_entries)
|
|
55
|
+
except (OSError, ValueError, Exception) as e:
|
|
56
|
+
pytest.fail(f'An error occurred, {e}')
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def test_scubaresults():
|
|
60
|
+
"""
|
|
61
|
+
Determine if ScubaResults.json contains API errors or exceptions.
|
|
62
|
+
"""
|
|
63
|
+
try:
|
|
64
|
+
output_path = get_output_path()
|
|
65
|
+
verify_scubaresults(output_path)
|
|
66
|
+
except (ValueError, Exception) as e:
|
|
67
|
+
pytest.fail(f'An error occurred, {e}')
|
|
68
|
+
|
|
69
|
+
@staticmethod
|
|
70
|
+
def test_scubagoggles_report(browser, customerdomain):
|
|
71
|
+
"""
|
|
72
|
+
Test if the generated baseline reports are correct,
|
|
73
|
+
i.e. BaselineReports.html, CalendarReport.html, ChatReport.html
|
|
74
|
+
"""
|
|
75
|
+
try:
|
|
76
|
+
output_path = get_output_path()
|
|
77
|
+
report_path: str = top_report_url(output_path)
|
|
78
|
+
browser.get(report_path)
|
|
79
|
+
run_selenium(browser, customerdomain)
|
|
80
|
+
except (ValueError, AssertionError, Exception) as e:
|
|
81
|
+
browser.quit()
|
|
82
|
+
pytest.fail(f'An error occurred, {e}')
|