Skip to content

Commit a960be1

Browse files
Added docstrings to multiple functions and fixed issues addressed by SonarQube
1 parent a700602 commit a960be1

File tree

8 files changed

+94
-41
lines changed

8 files changed

+94
-41
lines changed

pages/generate_invitations_page.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def __init__(self, page: Page):
99
self.page = page
1010
# Generate Invitations - page links
1111
self.generate_invitations_button = self.page.get_by_role("button", name="Generate Invitations")
12-
self.displayRS = self.page.locator("#displayRS")
12+
self.display_rs = self.page.locator("#displayRS")
1313
self.refresh_button = self.page.get_by_role("button", name="Refresh")
1414
self.planned_invitations_total = self.page.locator("#col8_total")
1515
self.self_referrals_total = self.page.locator("#col9_total")
@@ -32,17 +32,17 @@ def wait_for_invitation_generation_complete(self) -> bool:
3232
pytest.fail("There are no planned invitations to generate")
3333

3434
# Initially, ensure the table contains "Queued"
35-
expect(self.displayRS).to_contain_text("Queued")
35+
expect(self.display_rs).to_contain_text("Queued")
3636

3737
# Set timeout parameters
3838
timeout = 120000 # Total timeout of 120 seconds (in milliseconds)
3939
wait_interval = 5000 # Wait 5 seconds between refreshes (in milliseconds)
4040
elapsed = 0
4141

4242
# Loop until the table no longer contains "Queued"
43-
logging.info(f"Waiting for successful generation")
43+
logging.info("Waiting for successful generation")
4444
while elapsed < timeout: # there may be a stored procedure to speed this process up
45-
table_text = self.displayRS.text_content()
45+
table_text = self.display_rs.text_content()
4646
if "Failed" in table_text:
4747
pytest.fail("Invitation has failed to generate")
4848
elif "Queued" in table_text or "In Progress" in table_text:
@@ -55,11 +55,11 @@ def wait_for_invitation_generation_complete(self) -> bool:
5555

5656
# Final check: ensure that the table now contains "Completed"
5757
try:
58-
expect(self.displayRS).to_contain_text("Completed")
58+
expect(self.display_rs).to_contain_text("Completed")
5959
logging.info("Invitations successfully generated")
6060
logging.info(f"Invitations took {elapsed / 1000} seconds to generate")
6161
except Exception as e:
62-
pytest.fail("Invitations not generated successfully")
62+
pytest.fail(f"Invitations not generated successfully: {str(e)}")
6363

6464
value = self.planned_invitations_total.text_content().strip() # Get text and remove extra spaces
6565
if int(value) < 5:

pages/subject_screening_page.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from playwright.sync_api import Page
22
from utils.click_helper import click
33

4-
54
class SubjectScreeningPage:
65
def __init__(self, page: Page):
76
self.page = page

pages/subject_screening_summary.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def __init__(self, page: Page):
1818
self.change_screening_status = self.page.get_by_label("Change Screening Status")
1919
self.reason = self.page.get_by_label("Reason", exact=True)
2020
self.update_subject_data = self.page.get_by_role("button", name="Update Subject Data")
21-
self.close_FOBT_screening_episode = self.page.get_by_role("button", name="Close FOBT Screening Episode")
21+
self.close_fobt_screening_episode = self.page.get_by_role("button", name="Close FOBT Screening Episode")
2222
self.go_to_a_page_to_advance_the_episode = self.page.get_by_text("go to a page to Advance the")
2323
self.go_to_a_page_to_close_the_episode = self.page.get_by_text("go to a page to Close the")
2424

@@ -65,8 +65,8 @@ def select_reason(self):
6565
def click_update_subject_data(self):
6666
click(self.page, self.update_subject_data)
6767

68-
def click_close_FOBT_screening_episode(self):
69-
click(self.page, self.close_FOBT_screening_episode)
68+
def click_close_fobt_screening_episode(self):
69+
click(self.page, self.close_fobt_screening_episode)
7070

7171
def go_to_a_page_to_advance_the_episode(self):
7272
click(self.page, self.go_to_a_page_to_advance_the_episode)

tests/smokescreen/bcss_smokescreen_tests.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
# ----------------------------------
88
# compartment 2
99
# ----------------------------------
10+
c2_normal_kits_to_log=9
1011
# c2_fit_kit_logging_test_org_id=23159
1112
# c2_eng_gfobt_kit_logging_test_org_id=23159
1213

tests/smokescreen/test_compartment_1.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from pages.call_and_recall_page import CallAndRecall
99
from pages.invitations_monitoring_page import InvitationsMonitoring
1010
from pages.invitations_plans_page import InvitationsPlans
11-
from pages.create_a_plan_page import *
11+
from pages.create_a_plan_page import CreateAPlan
1212
from pages.navigation_bar_links import NavigationBar
1313
from pages.generate_invitations_page import GenerateInvitations
1414
from playwright.sync_api import Page

tests/smokescreen/test_compartment_2.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,46 @@
1111
from utils.fit_kit_generation import create_fit_id_df
1212
from utils.screening_subject_page_searcher import verify_subject_event_status_by_nhs_no
1313
from utils.user_tools import UserTools
14+
from jproperties import Properties
15+
from sys import platform
1416

17+
@pytest.fixture
18+
def smokescreen_properties() -> dict:
19+
"""
20+
Reads the 'bcss_smokescreen_tests.properties' file and populates a 'Properties' object.
21+
Returns a dictionary of properties for use in tests.
22+
23+
Returns:
24+
dict: A dictionary containing the values loaded from the 'bcss_smokescreen_tests.properties' file.
25+
"""
26+
configs = Properties()
27+
if platform == "win32": # File path from content root is required on Windows OS
28+
with open('tests/smokescreen/bcss_smokescreen_tests.properties', 'rb') as read_prop:
29+
configs.load(read_prop)
30+
elif platform == "darwin": # Only the filename is required on macOS
31+
with open('bcss_smokescreen_tests.properties', 'rb') as read_prop:
32+
configs.load(read_prop)
33+
return configs.properties
1534

1635
@pytest.mark.smoke
1736
@pytest.mark.smokescreen
1837
@pytest.mark.compartment2
19-
def test_compartment_2(page: Page) -> None:
38+
def test_compartment_2(page: Page, smokescreen_properties: dict) -> None:
39+
"""
40+
This is the main compartment 2 function. It covers the following:
41+
- Obtaining test data from the DB
42+
- Creating FIT Device IDs from the obtained test data
43+
- Logging FIT Devices
44+
- Logging FIT Devices as Spoilt
45+
- Processing the generated S3 batch
46+
"""
2047
UserTools.user_login(page, "Hub Manager State Registered")
2148

2249
MainMenu(page).go_to_fit_test_kits_page()
2350
FITTestKits(page).go_to_log_devices_page()
2451
subjectdf = create_fit_id_df()
2552

26-
for subject in range(9):
53+
for subject in range(int(smokescreen_properties["c2_normal_kits_to_log"])):
2754
fit_device_id = subjectdf["fit_device_id"].iloc[subject]
2855
logging.info(f"Logging FIT Device ID: {fit_device_id}")
2956
LogDevices(page).fill_fit_device_id_field(fit_device_id)
@@ -33,8 +60,8 @@ def test_compartment_2(page: Page) -> None:
3360
try:
3461
LogDevices(page).verify_successfully_logged_device_text()
3562
logging.info(f"{fit_device_id} Successfully logged")
36-
except:
37-
pytest.fail(f"{fit_device_id} unsuccessfully logged")
63+
except Exception as e:
64+
pytest.fail(f"{fit_device_id} unsuccessfully logged: {str(e)}")
3865

3966
nhs_no = subjectdf["subject_nhs_number"].iloc[0]
4067
try:
@@ -56,8 +83,8 @@ def test_compartment_2(page: Page) -> None:
5683
try:
5784
LogDevices(page).verify_successfully_logged_device_text()
5885
logging.info(f"{spoilt_fit_device_id} Successfully logged")
59-
except:
60-
pytest.fail(f"{spoilt_fit_device_id} Unsuccessfully logged")
86+
except Exception as e:
87+
pytest.fail(f"{spoilt_fit_device_id} Unsuccessfully logged: {str(e)}")
6188

6289
batch_processing(page, "S3", "Retest (Spoilt) (FIT)", "S11 - Retest Kit Sent (Spoilt)")
6390

utils/fit_kit_generation.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@
44
import logging
55

66

7-
def create_fit_id_df():
7+
def create_fit_id_df() -> pd.DataFrame:
88
df = get_kit_id_from_db()
99
df["fit_device_id"] = df["kitid"].apply(calculate_check_digit)
1010
df["fit_device_id"] = df["fit_device_id"].apply(convert_kit_id_to_fit_device_id)
1111
return df
1212

13-
def calculate_check_digit(kitID: str):
14-
logging.info(f"Calculating check digit for kit id: {kitID}")
13+
def calculate_check_digit(kit_id: str) -> str:
14+
logging.info(f"Calculating check digit for kit id: {kit_id}")
1515
total = 0
16-
charString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"
17-
for i in range(len(kitID)):
18-
total += charString.index(kitID[i - 1])
19-
check_digit = charString[total % 43]
20-
return f"{kitID}-{check_digit}"
16+
char_string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"
17+
for i in range(len(kit_id)):
18+
total += char_string.index(kit_id[i - 1])
19+
check_digit = char_string[total % 43]
20+
return f"{kit_id}-{check_digit}"
2121

22-
def convert_kit_id_to_fit_device_id(kit_id: str):
22+
def convert_kit_id_to_fit_device_id(kit_id: str) -> str:
2323
logging.info(f"Generating FIT Device ID from: {kit_id}")
2424
today = datetime.now()
2525
year = today.strftime("%y") # Get the year from todays date in YY format

utils/oracle/oracle.py

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ def __init__(self):
1414
self.password = os.getenv("pw")
1515

1616
def connect_to_db(self) -> oracledb.Connection:
17+
"""
18+
This function is used to connect to the Oracle DB. All the credentials are retrieved from a .env file
19+
"""
1720
try:
1821
logging.info("Attempting DB connection...")
1922
conn = oracledb.connect(user=self.user, password=self.password, dsn=self.dns)
@@ -22,8 +25,16 @@ def connect_to_db(self) -> oracledb.Connection:
2225
except Exception as queryExecutionError:
2326
logging.error(f"Failed to to extract subject ID with error: {queryExecutionError}")
2427

28+
def disconnect_from_db(self, conn):
29+
conn.close()
30+
logging.info("Connection Closed")
2531

2632
def exec_bcss_timed_events(self, nhs_number_df): # Executes bcss_timed_events when given NHS numbers
33+
"""
34+
this function is used to execute bcss_timed_events against NHS Numbers.
35+
It expects the nhs_numbers to be in a dataframe, and runs a for loop to get the subject_screening_id for each nhs number
36+
Once a subject_screening_id is retrieved, it will then run the command: exec bcss_timed_events [<subject_id>,'Y']
37+
"""
2738
conn = self.connect_to_db()
2839
try:
2940
for index, row in nhs_number_df.iterrows():
@@ -40,10 +51,12 @@ def exec_bcss_timed_events(self, nhs_number_df): # Executes bcss_timed_events w
4051
logging.error(f"Failed to to extract subject ID with error: {queryExecutionError}")
4152
finally:
4253
if conn is not None:
43-
conn.close()
44-
logging.info("Connection closed")
54+
self.disconnect_from_db(conn)
4555

4656
def get_subject_id_from_nhs_number(self, nhs_number) -> str:
57+
"""
58+
This function is used to obtain the subject_screening_id of a subject when given an nhs number
59+
"""
4760
conn = self.connect_to_db()
4861
logging.info(f"Attempting to get subject_id from nhs number: {nhs_number}")
4962
cursor = conn.cursor()
@@ -55,6 +68,9 @@ def get_subject_id_from_nhs_number(self, nhs_number) -> str:
5568
return subject_id
5669

5770
def populate_ui_approved_users_table(self, user: str): # To add users to the UI_APPROVED_USERS table
71+
"""
72+
This function is used to add a user to the UI_APPROVED_USERS table
73+
"""
5874
conn = self.connect_to_db()
5975
try:
6076
logging.info("Attempting to write to the db...")
@@ -66,41 +82,49 @@ def populate_ui_approved_users_table(self, user: str): # To add users to the UI
6682
logging.error(f"Failed to write to the DB! with write error {dbWriteError}")
6783
finally:
6884
if conn is not None:
69-
conn.close()
70-
logging.info("Connection closed")
85+
self.disconnect_from_db(conn)
7186

7287
def delete_all_users_from_approved_users_table(self): # To remove all users from the UI_APPROVED_USERS table
88+
"""
89+
This function is used to remove users from the UI_APPROVED_USERS table where OE_USER_CODE is not null
90+
"""
7391
conn = self.connect_to_db()
7492
try:
7593
logging.info("Attempting to delete users from DB table...")
7694
cursor = conn.cursor()
77-
cursor.execute(f"DELETE FROM UI_APPROVED_USERS WHERE OE_USER_CODE is not null")
95+
cursor.execute("DELETE FROM UI_APPROVED_USERS WHERE OE_USER_CODE is not null")
7896
conn.commit()
7997
logging.info("DB table values successfully deleted!")
8098
except Exception as dbValuesDeleteError:
8199
logging.error(
82100
f"Failed to delete values from the DB table! with data deletion error {dbValuesDeleteError}")
83101
finally:
84102
if conn is not None:
85-
conn.close()
86-
logging.info("Connection Closed")
103+
self.disconnect_from_db(conn)
87104

88105
def execute_query(self, query: str) -> pd.DataFrame: # To use when "select xxxx" (stored procedures)
106+
"""
107+
This is used to execute any sql queries.
108+
A query is provided and then the result is returned as a pandas dataframe
109+
"""
89110
conn = self.connect_to_db()
90111
engine = create_engine('oracle+oracledb://', creator=lambda: conn)
91112
try:
92-
logging.info(f"Attempting to execute query")
113+
logging.info("Attempting to execute query")
93114
df = pd.read_sql(query, engine)
94-
logging.info("query execution successful!")
115+
logging.info("Query execution successful!")
95116
except Exception as executionError:
96117
logging.error(f"Failed to execute query with execution error {executionError}")
97118
finally:
98119
if conn is not None:
99-
conn.close()
100-
logging.info("Connection Closed - Returning results")
120+
self.disconnect_from_db(conn)
101121
return df
102122

103123
def execute_stored_procedure(self, procedure: str): # To use when "exec xxxx" (stored procedures)
124+
"""
125+
This is to be used whenever we need to execute a stored procedure.
126+
It is provided with the stored procedure name and then executes it
127+
"""
104128
conn = self.connect_to_db()
105129
try:
106130
logging.info(f"Attempting to execute stored procedure: {procedure}")
@@ -112,10 +136,13 @@ def execute_stored_procedure(self, procedure: str): # To use when "exec xxxx" (
112136
logging.error(f"Failed to execute stored procedure with execution error: {executionError}")
113137
finally:
114138
if conn is not None:
115-
conn.close()
116-
logging.info("Connection Closed")
139+
self.disconnect_from_db(conn)
117140

118141
def update_or_insert_data_to_table(self, statement, params): # To update or insert data into a table
142+
"""
143+
This is used to update or insert data into a table.
144+
It is provided with the SQL statement along with the arguments
145+
"""
119146
conn = self.connect_to_db()
120147
try:
121148
logging.info("Attempting to insert/update table")
@@ -127,5 +154,4 @@ def update_or_insert_data_to_table(self, statement, params): # To update or ins
127154
logging.error(f"Failed to insert/update values from the DB table! with error {dbUpdateInsertError}")
128155
finally:
129156
if conn is not None:
130-
conn.close()
131-
logging.info("Connection Closed")
157+
self.disconnect_from_db(conn)

0 commit comments

Comments
 (0)