diff --git a/fieldExtraction/scripts/qa_qc.py b/fieldExtraction/scripts/qa_qc.py index 2cbd3eb..b737b45 100644 --- a/fieldExtraction/scripts/qa_qc.py +++ b/fieldExtraction/scripts/qa_qc.py @@ -18,7 +18,7 @@ from qa_qc_helpers import ( from consolidate_output import consolidate_adhoc -file_name_column = config.CONTRACT_FILE_NAME +file_name_column = config.FILE_NAME_COLUMN """python scripts/qa_qc.py input_dir=______ output_dir=_______ ac_df=________ b_df=______ read_mode=____ df_read_mode=________ You should have both input and output (ouput is just an empty folder) and then one of ac_df or b_df or both diff --git a/fieldExtraction/src/config.py b/fieldExtraction/src/config.py index 802bde1..05ae1c4 100644 --- a/fieldExtraction/src/config.py +++ b/fieldExtraction/src/config.py @@ -225,6 +225,7 @@ ANSWER_TRACKING_DICT = {} ######################################## POSTPROCESSING SETTINGS ######################################## FUZZY_MATCH_THRESHOLD = 0.8 FILE_NAME_COLUMN = 'Contract Name' +BLANKS_THRESHOLD = 0.5 ######################################## COMPLEX FLAG SETTINGS ######################################## COMPLEX_MAX_WORKERS = 50 diff --git a/fieldExtraction/src/consolidate_output.py b/fieldExtraction/src/consolidate_output.py index 4553eaf..144e8e7 100644 --- a/fieldExtraction/src/consolidate_output.py +++ b/fieldExtraction/src/consolidate_output.py @@ -137,8 +137,10 @@ def consolidate_adhoc(ac_df, b_df): # If ABC + b_df.drop([col for col in ["Pages", "Parent Agreement Code"] if col in b_df.columns], axis=1, inplace=True) + abc_final_df = pd.merge( - b_df, ac_df, on=[config.FILE_NAME_COLUMN, "Pages", "Parent Agreement Code"], how="right" + b_df, ac_df, on=[config.FILE_NAME_COLUMN], how="right" ) abc_final_df = abc_final_df[ [col for col in valid.ABC_COLUMNS if col in abc_final_df] diff --git a/fieldExtraction/src/qa_qc_helpers.py b/fieldExtraction/src/qa_qc_helpers.py index 4b7affe..ac9021e 100644 --- a/fieldExtraction/src/qa_qc_helpers.py +++ b/fieldExtraction/src/qa_qc_helpers.py @@ -10,6 +10,7 @@ import preprocessing_funcs import config from openpyxl import Workbook from openpyxl.utils.dataframe import dataframe_to_rows +from hotfix_helper_funcs import keywords_to_detect_invalid_state_name def detect_date_anomalies(series, field_name, is_merged=False): total_count = len(series) @@ -48,17 +49,20 @@ def detect_date_anomalies(series, field_name, is_merged=False): return result def tin_check(tin: str) -> tuple[str, bool]: - pattern = r'\b\d{2}-\d{7}\b' + pattern = r'^\b\d{2}-\d{7}\b$' if not isinstance(tin, str): try: tin = str(tin) - except TypeError: + except Exception: check = False return tin, check - check=bool(re.match(pattern, tin)) + match=re.match(pattern, tin) + check = bool(match) + + tin = match.group(0) if match else tin return tin, check @@ -68,12 +72,15 @@ def npi_check(npi: str) -> tuple[str, bool]: if not isinstance(npi, str): try: npi = str(npi) - except TypeError: + except Exception: check = False return npi, check - check = bool(re.match(pattern, npi)) + match = re.match(pattern, npi) + check = bool(match) + + npi = match.group(0) if match else npi return npi, check @@ -81,9 +88,15 @@ def date_format_check(date: str) -> tuple: format = '%m/%d/%Y' + if not isinstance(date, str): + try: + date = str(date) + except TypeError: + check = False + date = date try: dt = datetime.strptime(date, format) - date = dt.strftime('%m/%d/%Y') + date = dt.strftime('%-m/%-d/%Y') check = True except ValueError: date = date @@ -112,35 +125,66 @@ def state_check(state: str) -> tuple[str, bool]: check = False return state, check - if state in STATE_MAP.keys(): - state = STATE_MAP[state] + if state.upper() in STATE_MAP.keys(): + state = STATE_MAP[state.upper()] check = True elif state.strip().title() in STATE_MAP.values(): check = True + state = state.strip().title() else: check = False return state, check -def pages_pagenum_check(pages: str, pagenum: str) -> bool: +def pages_pagenum_check(pages: int, pagenum: int) -> bool: - if not isinstance(pages, str): + if not isinstance(pages, int): try: - pages = str(pages) - except TypeError: + pages = int(pages) + except (TypeError, ValueError) as e: check = False - return check - elif not isinstance(pagenum, str): - try: - pagenum = str(pagenum) - except TypeError: - check = False - return check - else: - check = (pagenum < pages) - return check + return check + + if not isinstance(pagenum, int): + try: + pagenum = int(pagenum) + except (TypeError, ValueError) as e: + check = False + + return check + + check = (pages >= pagenum) + + return check +def blanks_check(df: pd.DataFrame, threshold=config.BLANKS_THRESHOLD) -> pd.DataFrame: + + highly_blank_cols = [] + for col in df.columns: + if df[col].apply(lambda x: utils.is_empty(x)).sum() / len(df[col]) > threshold: + highly_blank_cols.append(col) + + return '\n'.join(highly_blank_cols) + +def self_talk_check(df: pd.DataFrame): + + lang_cols = [col for col in df.columns if ('Language' in col or 'Clause' in col) and ('(Y/N)' not in col)] + + selftalkers = [] + + for col in lang_cols: + + df['selftalk'] = df[col].apply(lambda x: any([(kw in x) for kw in keywords_to_detect_invalid_state_name]) if not utils.is_empty(x) else False) + + if df['selftalk'].any(): + + pct = df['selftalk'].sum() / len(df['selftalk']) + + selftalkers.append(f'{col} - {pct:.1%}') + + + return '\n'.join(selftalkers) def perform_qc_qa_tests_both(ac_df, b_df, merged_df, input_dict, processed_files): @@ -192,6 +236,8 @@ def perform_qc_qa_tests_both(ac_df, b_df, merged_df, input_dict, processed_files "Number of duplicate rows in merged DataFrame": merged_df.duplicated().sum(), "# of fields for AC run" : len(ac_df.columns), "# of fields for B run" : len(b_df.columns), + "Highly Blank Fields in merged DataFrame" : blanks_check(merged_df), + "Potential 'Self-Talk' columns in merged DataFrame" : self_talk_check(merged_df), "# of incorrectly formatted Provider Group TINs" : ac_df["IRS #"].apply(lambda x: not tin_check(x)[1] if not utils.is_empty(x) else False).sum(), "# of incorrectly formatted Provider Group NPIs" : ac_df["NPI (10-digits)"].apply(lambda x: not npi_check(x)[1] if not utils.is_empty(x) else False).sum(), "# of incorrectly formatted Provider Group Signatory TINs": ac_df["PROV_GROUP_TIN_SIGNATORY"].apply(lambda x: not tin_check(x)[1] if not utils.is_empty(x) else False).sum(), @@ -199,7 +245,7 @@ def perform_qc_qa_tests_both(ac_df, b_df, merged_df, input_dict, processed_files "# of incorrectly formatted Provider NPIs (other)": ac_df["PROV_NPI_OTHER"].apply(lambda x: not npi_check(x)[1] if not utils.is_empty(x) else False).sum(), "# of incorrect Health Plan States" : ac_df['Health Plan State'].apply(lambda x: not state_check(x)[1] if not utils.is_empty(x) else False).sum(), "# of rows with Pages greater than Page Num" : merged_df.apply(lambda row: pages_pagenum_check(row['Pages'], row['Page_Num']) if (not utils.is_empty(row['Pages']) and utils.is_empty(row['Page_Num'])) else False, axis=1).sum(), - "# of Payer Names found in Notice to Provider Name" : ac_df.apply(lambda row: row['PAYER NAME'] in row['Notice to Provider Name'] if not utils.is_empty(row['Notice to Provider Name']) else False, axis = 1).sum(), + "# of Payer Names found in Notice to Provider Name" : ac_df.apply(lambda row: row['PAYER NAME'] in row['Notice to Provider Name'] if not utils.is_empty(row['Notice to Provider Name']) and not utils.is_empty(row['PAYER NAME']) else False, axis = 1).sum(), "# of invalid Y/N values for B run" : b_df[yn_cols_b].apply(lambda x: yn_check(x)[1], axis = 1).sum().sum(), "# of invalid Y/N values for AC run" : ac_df[yn_cols_ac].apply(lambda x: yn_check(x)[1], axis = 1).sum().sum(), "# of invalid Termination Dates" : ac_df['Termination Date'].apply(lambda x: not date_format_check(x) if not utils.is_empty(x) else x).sum(), @@ -269,6 +315,8 @@ def perform_qc_qa_tests_ac(ac_df, input_dict, processed_files): .sum(), "# of duplicate rows for AC run": ac_df.duplicated().sum(), "# of fields for AC run" : len(ac_df.columns), + "Highly Blank Fields in AC DataFrame" : blanks_check(ac_df), + "Potential 'Self-Talk' columns in merged DataFrame" : self_talk_check(ac_df), "# of incorrectly formatted Provider Group TINs" : ac_df["IRS #"].apply(lambda x: not tin_check(x)[1] if not utils.is_empty(x) else False).sum(), "# of incorrectly formatted Provider Group NPIs" : ac_df["NPI (10-digits)"].apply(lambda x: not npi_check(x)[1] if not utils.is_empty(x) else False).sum(), "# of incorrectly formatted Provider Group Signatory TINs": ac_df["PROV_GROUP_TIN_SIGNATORY"].apply(lambda x: not tin_check(x)[1] if not utils.is_empty(x) else False).sum(), @@ -321,6 +369,8 @@ def perform_qc_qa_tests_b(b_df, input_dict, processed_files): .sum(), "# of duplicate rows for B run": b_df.duplicated().sum(), "# of fields for B run" : len(b_df.columns), + "Highly Blank Fields in B DataFrame" : blanks_check(b_df), + "Potential 'Self-Talk' columns in merged DataFrame" : self_talk_check(b_df), "# of rows with Pages greater than Page Num" : b_df.apply(lambda row: pages_pagenum_check(row['Pages'], row['Page_Num']), axis=1).sum(), "# of invalid Y/N values for B run" : b_df[yn_cols_b].apply(lambda x: yn_check(x)[1], axis = 1).sum().sum()} @@ -500,7 +550,7 @@ def save_qcqa_wb(wb, run_timestamp): # Upload to S3 if config.WRITE_TO_S3: BUCKET_NAME = config.S3_OUTPUT_BUCKET - print(f"Uploading final outputs to s3://{BUCKET_NAME}/{run_timestamp}") + print(f"Uploading final outputs to s3://{BUCKET_NAME}/qcqa/{run_timestamp}") # Upload consolidated outputs diff --git a/fieldExtraction/tests/qcqa/blanks_test.py b/fieldExtraction/tests/qcqa/blanks_test.py new file mode 100644 index 0000000..923618f --- /dev/null +++ b/fieldExtraction/tests/qcqa/blanks_test.py @@ -0,0 +1,41 @@ +import pytest +import pandas as pd +import sys +sys.path.append('src') +from qa_qc_helpers import blanks_check + + +def test_blanks_check_no_highly_blank_columns(): + # Create a sample DataFrame with no highly blank columns + df = pd.DataFrame({ + "A": [1, 2, 3, 4, 5], + "B": ["a", "b", "c", "d", "e"], + "C": [10.5, 11.2, 12.3, 13.4, 14.5] + }) + + result = blanks_check(df) + assert result == "" + +def test_blanks_check_with_highly_blank_columns(): + # Create a sample DataFrame with highly blank columns + df = pd.DataFrame({ + "A": [1, 2, 3, None, 5, None, 6], + "B": ["a", "b", "", "d", "", "", ""], + "C": [10.5, None, 12.3, None, 14.5, None, None] + }) + + result = blanks_check(df) + expected_output = "B\nC" + assert result == expected_output + +def test_blanks_check_all_columns_highly_blank(): + # Create a sample DataFrame where all columns are highly blank + df = pd.DataFrame({ + "A": [None, None, None, None, None], + "B": ["", "", "", "", ""], + "C": [None, None, None, None, None] + }) + + result = blanks_check(df) + expected_output = "A\nB\nC" + assert result == expected_output \ No newline at end of file diff --git a/fieldExtraction/tests/qcqa/date_format_test.py b/fieldExtraction/tests/qcqa/date_format_test.py new file mode 100644 index 0000000..0761d17 --- /dev/null +++ b/fieldExtraction/tests/qcqa/date_format_test.py @@ -0,0 +1,84 @@ +import pytest +from datetime import datetime +import sys +sys.path.append('src') +from qa_qc_helpers import date_format_check + +def test_valid_date_formats(): + """Test valid date formats are correctly validated""" + valid_dates = { + "01/01/2024" : '1/1/2024', + "12/31/2023" : '12/31/2023', + "02/29/2024" : '2/29/2024', # Leap year + "07/04/1776" : '7/4/1776', + "09/08/2024" : '9/8/2024' + } + + for date in valid_dates.keys(): + result, is_valid = date_format_check(date) + assert result == valid_dates[date] + assert is_valid is True + +def test_invalid_date_formats(): + """Test various invalid date formats""" + invalid_dates = [ + "13/01/2024", # Invalid month + "01/32/2024", # Invalid day + "02/29/2023", # Not a leap year + "00/01/2024", # Zero month + "01/00/2024", # Zero day + "01-01-2024", # Wrong separator + "2024/01/01", # Wrong order + "01/01/24", # Two-digit year + "Jan/01/2024", # Text month + ] + + for date in invalid_dates: + result, is_valid = date_format_check(date) + assert result == date + assert is_valid is False + +def test_non_string_inputs(): + """Test handling of non-string inputs""" + test_cases = [ + (20240101, "20240101"), + (None, None), + (1.234, "1.234"), + (["01/01/2024"], "['01/01/2024']"), + ({"date": "01/01/2024"}, "{'date': '01/01/2024'}"), + ] + + for input_val, expected_str in test_cases: + result, is_valid = date_format_check(input_val) + assert result == str(input_val) + assert is_valid is False + +def test_edge_cases(): + """Test edge cases with valid-looking but incorrect formats""" + test_cases = [ + "01/01/2024 ", # Extra space at end + " 01/01/2024", # Extra space at start + "01/01/2024\n", # Newline at end + "01 /01/2024", # Space in middle + "01/01/ 2024", # Space in middle + ] + + for date in test_cases: + result, is_valid = date_format_check(date) + assert result == date + assert is_valid is False + +def test_special_dates(): + """Test boundary cases for dates""" + test_cases = [ + ("12/31/9999", True), # Far future + ("2/28/2024", True), # Day before leap day + ("3/1/2024", True), # Day after leap day + ("12/31/2023", True), # Last day of year + ("1/1/2024", True), # First day of year + ] + + for date, expected_valid in test_cases: + result, is_valid = date_format_check(date) + assert result == date + assert is_valid == expected_valid \ No newline at end of file diff --git a/fieldExtraction/tests/qcqa/npi_test.py b/fieldExtraction/tests/qcqa/npi_test.py new file mode 100644 index 0000000..63e5df8 --- /dev/null +++ b/fieldExtraction/tests/qcqa/npi_test.py @@ -0,0 +1,67 @@ +import pytest +import sys +sys.path.append('src') +from qa_qc_helpers import npi_check +import re + +def test_valid_npi_format(): + """Test that a correctly formatted NPI returns True""" + npi = "1234567890" + result, is_valid = npi_check(npi) + assert result == npi + assert is_valid is True + +def test_invalid_npi_format(): + """Test various invalid NPI formats""" + invalid_npis = [ + "123456789", # Too few digits + "12345678900", # Too many digits + "12-4567890", # TIN format + "1ab3456789", # Letters instead of numbers + "3234567890", # Doesn't start with 1 or 2 + ] + + for npi in invalid_npis: + result, is_valid = npi_check(npi) + assert result == npi + assert is_valid is False + +def test_non_string_inputs(): + """Test handling of non-string inputs""" + test_cases = [ + (1234567890, "1234567890", True), + (12.3456789, "12.3456789", False), + (None, 'None', False), + ([12, 3456789], "[12, 3456789]", False), + ({"npi" : "1234567890"}, "{'npi': '1234567890'}", False), + ] + + for input_val, expected_str, expected_valid in test_cases: + result, is_valid = npi_check(input_val) + assert result == expected_str + assert is_valid is expected_valid + +def test_edge_cases_npi(): + """Test edge cases with valid-looking but incorrect formats""" + test_cases = [ + "12345 67890" # Space in middle + ] + + for npi in test_cases: + result, is_valid = npi_check(npi) + assert result == npi + assert is_valid is False + +def test_multiple_tins_in_string(): + """Test strings containing multiple TIN-like patterns""" + test_cases = [ + "1234567890 1256789001", # Two TINs with space + "12345678901234567890", # Two TINs without space + "Some text 1234567890", # TIN with preceding text + "1234567890 some text", # TIN with following text + ] + + for npi in test_cases: + result, is_valid = npi_check(npi) + assert result == npi + assert is_valid is False \ No newline at end of file diff --git a/fieldExtraction/tests/qcqa/pages_pagenum_test.py b/fieldExtraction/tests/qcqa/pages_pagenum_test.py new file mode 100644 index 0000000..c86e41c --- /dev/null +++ b/fieldExtraction/tests/qcqa/pages_pagenum_test.py @@ -0,0 +1,41 @@ +import pytest +import sys +sys.path.append('src') +from qa_qc_helpers import pages_pagenum_check + +def test_pages_pagenum_check_valid_inputs(): + # Test with valid string inputs + assert pages_pagenum_check("100", "50") is True + assert pages_pagenum_check(50, 10) is True + +def test_pages_pagenum_check_invalid_inputs(): + # Test with invalid string inputs + assert pages_pagenum_check("abc", "50") is False + assert pages_pagenum_check("50", "xyz") is False + +def test_pages_pagenum_check_non_string_inputs(): + # Test with non-string inputs for pages + assert pages_pagenum_check(100, "50") is True + assert pages_pagenum_check(50, 10) is True + + # Test with non-string inputs for pagenum + assert pages_pagenum_check("100", 50) is True + assert pages_pagenum_check("50", 10) is True + +def test_pages_pagenum_check_non_convertible_inputs(): + # Test with inputs that cannot be converted to string for pages + def raise_type_error(): + raise TypeError("Cannot convert to string") + + assert pages_pagenum_check(raise_type_error, "50") is False + + # Test with inputs that cannot be converted to string for pagenum + assert pages_pagenum_check("100", raise_type_error) is False + +def test_pages_pagenum_check_equality(): + # Test when pages and pagenum are equal + assert pages_pagenum_check("100", "100") is True + +def test_pages_pagenum_check_pagenum_greater(): + # Test when pagenum is greater than pages + assert pages_pagenum_check("50", "100") is False \ No newline at end of file diff --git a/fieldExtraction/tests/qcqa/selftalk_test b/fieldExtraction/tests/qcqa/selftalk_test new file mode 100644 index 0000000..bb7f13b --- /dev/null +++ b/fieldExtraction/tests/qcqa/selftalk_test @@ -0,0 +1,42 @@ +import pytest +import pandas as pd +import sys +sys.path.append('src') +from qa_qc_helpers import self_talk_check +from hotfix_helper_funcs import keywords_to_detect_invalid_state_name + + +def test_self_talk_check_no_self_talk(): + # Create a sample DataFrame with no self-talk columns + df = pd.DataFrame({ + "Name": ["John", "Jane", "Bob", "Alice", "Tom"], + "Age": [25, 30, 35, 40, 45], + "City": ["New York", "Los Angeles", "Chicago", "Houston", "Miami"] + }) + + result = self_talk_check(df) + assert result == "" + +def test_self_talk_check_with_self_talk(): + # Create a sample DataFrame with self-talk columns + df = pd.DataFrame({ + "Name": ["John", "Jane", "Bob", "Alice", "Tom"], + "Language": ["English", "Spanish", "The Contract Text suggests Armenian", "French", "German"], + "Clause": ["", "this suggests", "Mike refers to xyz", "The Contract Text says", "My Answer is this: "] + }) + + result = self_talk_check(df) + expected_output = "Language - 20.0%\nClause - 80.0%" + assert result == expected_output + +def test_self_talk_check_all_self_talk(): + # Create a sample DataFrame where all language columns have self-talk + df = pd.DataFrame({ + "Name": ["John", "Jane", "Bob", "Alice", "Tom"], + "Language": ["Statewide", "Multiple sources imply", "The contract text says", "For this text, it would seem", "This suggests that"], + "Clause": ["The Contract Text contains this", "My Answer Is This: ", "It would seem that multiple clauses say", "I conclude that the exhibit suggests", "For each clause, this is the case"] + }) + + result = self_talk_check(df) + expected_output = "Language - 100.0%\nClause - 100.0%" + assert result == expected_output \ No newline at end of file diff --git a/fieldExtraction/tests/qcqa/state_test.py b/fieldExtraction/tests/qcqa/state_test.py new file mode 100644 index 0000000..3dab22a --- /dev/null +++ b/fieldExtraction/tests/qcqa/state_test.py @@ -0,0 +1,32 @@ +import pytest +import sys +sys.path.append('src') +from qa_qc_helpers import state_check + + +def test_state_check_valid_abbreviations(): + # Test with valid state abbreviations + assert state_check("CA") == ("California", True) + assert state_check("NY") == ("New York", True) + +def test_state_check_valid_full_names(): + # Test with valid state full names + assert state_check("California") == ("California", True) + assert state_check("new york") == ("New York", True) + +def test_state_check_invalid_input(): + # Test with invalid input + assert state_check("ABC") == ("ABC", False) + assert state_check("Invalid State") == ("Invalid State", False) + +def test_state_check_non_string_input(): + # Test with non-string input + assert state_check(123) == ("123", False) + assert state_check(True) == ("True", False) + +def test_state_check_non_convertible_input(): + # Test with input that cannot be converted to string + def raise_type_error(): + raise TypeError("Cannot convert to string") + + assert state_check(raise_type_error)[1] == False \ No newline at end of file diff --git a/fieldExtraction/tests/qcqa/tin_test.py b/fieldExtraction/tests/qcqa/tin_test.py new file mode 100644 index 0000000..a97b251 --- /dev/null +++ b/fieldExtraction/tests/qcqa/tin_test.py @@ -0,0 +1,74 @@ +import pytest +import sys +sys.path.append('src') +from qa_qc_helpers import tin_check +import re + +def test_valid_tin_format(): + """Test that a correctly formatted TIN returns True""" + tin = "12-3456789" + result, is_valid = tin_check(tin) + assert result == tin + assert is_valid is True + +def test_invalid_tin_format(): + """Test various invalid TIN formats""" + invalid_tins = [ + "123-456789", # Too many digits before hyphen + "12-456789", # Too few digits after hyphen + "12-45678901", # Too many digits after hyphen + "12_3456789", # Wrong separator + "ab-3456789", # Letters instead of numbers + "12-abcdefg", # Letters instead of numbers + "123456789", # No hyphen + "-12345678", # Hyphen at start + "12-34567-", # Hyphen at end + ] + + for tin in invalid_tins: + result, is_valid = tin_check(tin) + assert result == tin + assert is_valid is False + +def test_non_string_inputs(): + """Test handling of non-string inputs""" + test_cases = [ + (123456789, "123456789", False), + (12.3456789, "12.3456789", False), + (None, 'None', False), + ([12, 3456789], "[12, 3456789]", False), + ({"tin":"12-3456789"}, "{'tin': '12-3456789'}", False), + ] + + for input_val, expected_str, expected_valid in test_cases: + result, is_valid = tin_check(input_val) + assert result == expected_str + assert is_valid is expected_valid + +def test_edge_cases(): + """Test edge cases with valid-looking but incorrect formats""" + test_cases = [ + "12 3456789", #Space instead of dash + "1 2-3456789", # Space at beginning + "12-345 6789", # Space in middle + ] + + for tin in test_cases: + result, is_valid = tin_check(tin) + assert result == tin + assert is_valid is False + +def test_multiple_tins_in_string(): + """Test strings containing multiple TIN-like patterns""" + test_cases = [ + "12-3456789 34-5678901", # Two TINs with space + "12-345678912-3456789", # Two TINs without space + "Some text 12-3456789", # TIN with preceding text + "12-3456789 some text", # TIN with following text + ] + + for tin in test_cases: + result, is_valid = tin_check(tin) + assert result == tin + assert is_valid is False + diff --git a/fieldExtraction/tests/qcqa/yn_test.py b/fieldExtraction/tests/qcqa/yn_test.py new file mode 100644 index 0000000..fb01ddb --- /dev/null +++ b/fieldExtraction/tests/qcqa/yn_test.py @@ -0,0 +1,26 @@ +import pytest +import sys +sys.path.append('src') +from qa_qc_helpers import yn_check + +def test_yn_check_with_valid_string_input(): + # Test with valid string inputs + assert yn_check("Y") == ("Y", True) + assert yn_check("N") == ("N", True) + +def test_yn_check_with_invalid_string_input(): + # Test with invalid string inputs + assert yn_check("a") == ("a", False) + assert yn_check("yes") == ("yes", False) + +def test_yn_check_with_non_string_input(): + # Test with non-string inputs + assert yn_check(1) == ("1", False) + assert yn_check(True) == ("True", False) + +def test_yn_check_with_non_convertible_input(): + # Test with inputs that cannot be converted to string + def raise_type_error(): + raise TypeError("Cannot convert to string") + + assert yn_check(raise_type_error)[1] == False \ No newline at end of file