向模拟测试添加返回参数

2024-10-01 15:47:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在Mike Rooney's Mint API进行此测试:

import copy
import datetime
import json
import unittest

import requests

try:
    from mock import patch  # Python 2
except ImportError:
    from unittest.mock import patch  # Python 3

import mintapi
import mintapi.api

accounts_example = [{
    "accountName": "Chase Checking",
    "lastUpdated": 1401201492000,
    "lastUpdatedInString": "25 minutes",
    "accountType": "bank",
    "currentBalance": 100.12,
}]


class MintApiTests(unittest.TestCase):
    @patch.object(mintapi.api, 'get_web_driver')
    def test_accounts(self, mock_driver):
        token_json = json.dumps({'token': '123'})
        mock_driver.return_value.find_element_by_name.return_value.get_attribute.return_value = token_json

        accounts_json = json.dumps({'response': {'42': {'response': accounts_example}}})
        mock_driver.return_value.request.return_value.text = accounts_json

        accounts = mintapi.get_accounts('foo', 'bar')

        self.assertFalse('lastUpdatedInDate' in accounts)
        self.assertNotEqual(accounts, accounts_example)

        accounts_annotated = copy.deepcopy(accounts_example)
        for account in accounts_annotated:
            account['lastUpdatedInDate'] = (datetime.datetime.fromtimestamp(account['lastUpdated'] / 1000))
        self.assertEqual(accounts, accounts_annotated)

        # ensure everything is json serializable as this is the command-line
        # behavior.
        mintapi.print_accounts(accounts)

    def test_chrome_driver_links(self):
        for platform in mintapi.api.CHROME_ZIP_TYPES:
            zip_type = mintapi.api.CHROME_ZIP_TYPES.get(platform)
            zip_file_url = mintapi.api.CHROME_DRIVER_BASE_URL % (mintapi.api.CHROME_DRIVER_VERSION, zip_type)
            request = requests.get(zip_file_url)
            self.assertEqual(request.status_code, 200)

    def test_parse_float(self):

        answer = mintapi.api.parse_float('10%')
        self.assertEqual(answer, float(10))

        answer = mintapi.api.parse_float('$10')
        self.assertEqual(answer, float(10))

        answer = mintapi.api.parse_float('0.00%')
        self.assertEqual(answer, float(0))

get_web_driver最初返回一个参数

我在get_web_driver中添加了一个额外的参数 因此,返回线如下所示:

    return driver, status_message

而不是

    return driver

真正的代码运行良好;我很难让特拉维斯通过考试。 我曾尝试以各种不同的方式添加一个额外的模拟参数,但测试失败,原因如下:

ValueError: not enough values to unpack (expected 2, got 0)

我有两个问题:

  1. 为什么模拟函数还没有返回一个参数
  2. 如何添加附加参数以传递*&;^%$%^测试

谢谢你能给我的任何帮助

以下是堆栈跟踪:

Error
Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/case.py", line 59, in testPartExecutor
    yield
  File "/usr/local/Cellar/python/3.7.6_1/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/case.py", line 628, in run
    testMethod()
  File "/usr/local/lib/python3.7/site-packages/mock/mock.py", line 1330, in patched
    return func(*args, **keywargs)
  File "/Users/jrt/Documents/projects/mintapi/mintapi/tests.py", line 34, in test_accounts
    accounts = mintapi.get_accounts('foo', 'bar')
  File "/Users/jrt/Documents/projects/mintapi/mintapi/api.py", line 973, in get_accounts
    mint = Mint.create(email, password)
  File "/Users/jrt/Documents/projects/mintapi/mintapi/api.py", line 377, in create
    return Mint(email, password, **opts)
  File "/Users/jrt/Documents/projects/mintapi/mintapi/api.py", line 373, in __init__
    wait_for_sync_timeout=wait_for_sync_timeout)
  File "/Users/jrt/Documents/projects/mintapi/mintapi/api.py", line 461, in login_and_get_token
    wait_for_sync_timeout=wait_for_sync_timeout)
ValueError: not enough values to unpack (expected 2, got 0)

下面是新的get_web_driver,它返回驱动程序和状态消息(最初只返回驱动程序)变量:

def get_web_driver(email, password, headless=False, mfa_method=None,
                   mfa_input_callback=None, wait_for_sync=True,
                   wait_for_sync_timeout=5 * 60,
                   session_path=None, imap_account=None, imap_password=None,
                   imap_server=None, imap_folder="INBOX"):
    if headless and mfa_method is None:
        warnings.warn("Using headless mode without specifying an MFA method"
                      "is unlikely to lead to a successful login. Defaulting --mfa-method=sms")
        mfa_method = "sms"

    zip_type = ""
    executable_path = os.getcwd() + os.path.sep + 'chromedriver'
    if _platform in ['win32', 'win64']:
        executable_path += '.exe'

    zip_type = CHROME_ZIP_TYPES.get(_platform)

    if not os.path.exists(executable_path):
        zip_file_url = CHROME_DRIVER_BASE_URL % (CHROME_DRIVER_VERSION, zip_type)
        request = requests.get(zip_file_url)

        if request.status_code != 200:
            raise RuntimeError('Error finding chromedriver at %r, status = %d' %
                               (zip_file_url, request.status_code))

        zip_file = zipfile.ZipFile(io.BytesIO(request.content))
        zip_file.extractall()
        os.chmod(executable_path, 0o755)

    chrome_options = ChromeOptions()
    if headless:
        chrome_options.add_argument('headless')
        chrome_options.add_argument('no-sandbox')
        chrome_options.add_argument('disable-dev-shm-usage')
        chrome_options.add_argument('disable-gpu')
        # chrome_options.add_argument("--window-size=1920x1080")
    if session_path is not None:
        chrome_options.add_argument("user-data-dir=%s" % session_path)

    driver = Chrome(chrome_options=chrome_options, executable_path="%s" % executable_path)
    driver.get("https://www.mint.com")
    driver.implicitly_wait(20)  # seconds
    try:
        element = driver.find_element_by_link_text("Sign in")
    except NoSuchElementException:
        # when user has cookies, a slightly different front page appears
        driver.implicitly_wait(0)  # seconds
        element = driver.find_element_by_link_text("Sign in")
        driver.implicitly_wait(20)  # seconds
    element.click()
    time.sleep(1)
    email_input = driver.find_element_by_id("ius-userid")
    # It's possible that the user clicked "remember me" at some point, causing
    # the email to already be present. If anything is in the input, clear it
    # and use the provided email, just to be safe.
    # email_input.setAttribute("value", "")
    email_input.clear()
    email_input.send_keys(email)
    driver.find_element_by_id("ius-password").send_keys(password)
    driver.find_element_by_id("ius-sign-in-submit-btn").submit()

    # Wait until logged in, just in case we need to deal with MFA.
    while not driver.current_url.startswith(
            'https://mint.intuit.com/overview.event'):
        # An implicitly_wait is also necessary here to avoid getting stuck on
        # find_element_by_id while the page is still in transition.
        driver.implicitly_wait(1)
        time.sleep(1)

        # bypass "Let's add your current mobile number" interstitial page
        try:
            skip_for_now = driver.find_element_by_id('ius-verified-user-update-btn-skip')
            skip_for_now.click()
        except (NoSuchElementException, StaleElementReferenceException, ElementNotVisibleException):
            pass

        driver.implicitly_wait(1)  # seconds
        try:
            if mfa_method == 'soft-token':
                mfa_token_input = driver.find_element_by_id('ius-mfa-soft-token')
                mfa_code = (mfa_input_callback or input)("Please enter your 6-digit MFA code: ")
                mfa_token_input.send_keys(mfa_code)
                mfa_token_submit = driver.find_element_by_id('ius-mfa-soft-token-submit-btn')
                mfa_token_submit.click()
            else:
                driver.find_element_by_id('ius-mfa-options-form')
                try:
                    mfa_method_option = driver.find_element_by_id('ius-mfa-option-{}'.format(mfa_method))
                    mfa_method_option.click()
                    mfa_method_submit = driver.find_element_by_id("ius-mfa-options-submit-btn")
                    mfa_method_submit.click()

                    if mfa_method == 'email' and imap_account:
                        mfa_code = get_email_code(imap_account, imap_password, imap_server, imap_folder=imap_folder)
                    else:
                        mfa_code = (mfa_input_callback or input)("Please enter your 6-digit MFA code: ")
                    mfa_code_input = driver.find_element_by_id("ius-mfa-confirm-code")
                    mfa_code_input.send_keys(mfa_code)

                    mfa_code_submit = driver.find_element_by_id("ius-mfa-otp-submit-btn")
                    mfa_code_submit.click()
                except Exception:  # if anything goes wrong for any reason, give up on MFA
                    mfa_method = None
                    warnings.warn("Giving up on handling MFA. Please complete "
                                  "the MFA process manually in the browser.")
        except NoSuchElementException:
            pass
        finally:
            driver.implicitly_wait(20)  # seconds

    # Wait until the overview page has actually loaded, and if wait_for_sync==True, sync has completed.
    status_message = None
    if wait_for_sync:
        try:
            # Status message might not be present straight away. Seems to be due
            # to dynamic content (client side rendering).
            status_message = WebDriverWait(driver, 30).until(
                expected_conditions.visibility_of_element_located(
                    (By.CSS_SELECTOR, ".SummaryView .message")))
            WebDriverWait(driver, wait_for_sync_timeout).until(
                lambda x: "Account refresh complete" in status_message.get_attribute('innerHTML')
            )
        except (TimeoutException, StaleElementReferenceException):
            status_message = "Mint sync apparently incomplete after timeout.  Data retrieved may not be current."
            warnings.warn(status_message)
    else:
        driver.find_element_by_id("transaction")

    if status_message is not None and isinstance(status_message, WebElement):
        status_message = status_message.text
    return driver, status_message

Tags: inmfaapiforinputgetbydriver
1条回答
网友
1楼 · 发布于 2024-10-01 15:47:53

感谢所有帮助过我的人,我终于解决了这个问题:

import copy
import datetime
import json
import unittest

import requests

try:
    from mock import patch  # Python 2
except ImportError:
    from unittest.mock import patch  # Python 3

import mintapi
import mintapi.api

accounts_example = [{
    "accountName": "Chase Checking",
    "lastUpdated": 1401201492000,
    "lastUpdatedInString": "25 minutes",
    "accountType": "bank",
    "currentBalance": 100.12,
}]


class Attribute:
    text = json.dumps({'response': {'42': {'response': accounts_example}}})


class Element:
    @staticmethod
    def get_attribute(test):
        return json.dumps({'token': '123'})


class TestMock:
    @staticmethod
    def find_element_by_name(test):
        return Element()

    @staticmethod
    def request(a, b, **c):
        return Attribute()


class MintApiTests(unittest.TestCase):
    @patch.object(mintapi.api, 'get_web_driver')
    def test_accounts(self, mock_driver):
        mock_driver.return_value = (TestMock(), "test")
        accounts = mintapi.get_accounts('foo', 'bar')

        self.assertFalse('lastUpdatedInDate' in accounts)
        self.assertNotEqual(accounts, accounts_example)

        accounts_annotated = copy.deepcopy(accounts_example)
        for account in accounts_annotated:
            account['lastUpdatedInDate'] = (datetime.datetime.fromtimestamp(account['lastUpdated'] / 1000))
        self.assertEqual(accounts, accounts_annotated)

        # ensure everything is json serializable as this is the command-line
        # behavior.
        mintapi.print_accounts(accounts)

    def test_chrome_driver_links(self):
        for platform in mintapi.api.CHROME_ZIP_TYPES:
            zip_type = mintapi.api.CHROME_ZIP_TYPES.get(platform)
            zip_file_url = mintapi.api.CHROME_DRIVER_BASE_URL % (mintapi.api.CHROME_DRIVER_VERSION, zip_type)
            request = requests.get(zip_file_url)
            self.assertEqual(request.status_code, 200)

    def test_parse_float(self):

        answer = mintapi.api.parse_float('10%')
        self.assertEqual(answer, float(10))

        answer = mintapi.api.parse_float('$10')
        self.assertEqual(answer, float(10))

        answer = mintapi.api.parse_float('0.00%')
        self.assertEqual(answer, float(0))

相关问题 更多 >

    热门问题