Skip to content

Conversation

@Voyz
Copy link
Owner

@Voyz Voyz commented Dec 24, 2025

This PR converts all remaining unittest tests into pytest.

One test file was already in pytest - unit/client/test_ibkr_client_u and was not touched during this refactor.

The migration has been carried out by AI agents - Google Jules and ChatGPT 5.2 through Windsurf. I then then manually reviewed each test, compared against the original, checked coverage and its intended functionality, and adjusted where needed.


Substantial simplifications were introduced to websocket tests, removing the _run_in_context functions and effectively flattening the resulting tests.

Also, the SafeAssertLogs and RaiseLogsContext in the test_utils were replaced by the capture_logs decorator.


@weklund - tagging you here in case you'd like to give this PR a review, though no worries if you're busy.


There is a tiny discrepancy between the resulting coverage since the pytest broke out some tests and effectively increased coverage.

Unittest coverage:

---------- coverage: platform win32, python 3.13.11-final-0 ----------
Name                                                  Stmts   Miss  Cover   Missing
-----------------------------------------------------------------------------------
ibind\__init__.py                                        13      0   100%
ibind\base\__init__.py                                    0      0   100%
ibind\base\queue_controller.py                           18      0   100%
ibind\base\rest_client.py                               152     35    77%   103, 110, 235, 240, 252, 265-275, 280-284, 296-297, 306-308, 311, 334-337, 340-346, 355
ibind\base\subscription_controller.py                   125     33    74%   65, 67-69, 74-75, 86, 89, 92, 100-101, 154, 173-191, 211, 283, 286, 289-292, 326, 334, 358
ibind\base\ws_client.py                                 217     38    82%   64, 90, 95, 118-120, 124-129, 151, 155-156, 168-169, 190, 196-198, 202-204, 238, 247, 254-256, 317-322, 363, 439-440, 457, 470
ibind\client\__init__.py                                  0      0   100%
ibind\client\ibkr_client.py                             119     69    42%   87-91, 116-119, 132-135, 143-149, 163-164, 195-218, 234-237, 250-251, 254-256, 265-267, 270-272, 286, 289-333
ibind\client\ibkr_client_mixins\__init__.py               0      0   100%
ibind\client\ibkr_client_mixins\accounts_mixin.py         4      0   100%
ibind\client\ibkr_client_mixins\contract_mixin.py        25      0   100%
ibind\client\ibkr_client_mixins\marketdata_mixin.py      61     29    52%   54-85, 226, 236-241, 303
ibind\client\ibkr_client_mixins\order_mixin.py           22     12    45%   102-110, 175-183
ibind\client\ibkr_client_mixins\portfolio_mixin.py        5      0   100%
ibind\client\ibkr_client_mixins\scanner_mixin.py          5      0   100%
ibind\client\ibkr_client_mixins\session_mixin.py         39     13    67%   105, 130-145
ibind\client\ibkr_client_mixins\watchlist_mixin.py        4      0   100%
ibind\client\ibkr_definitions.py                          6      0   100%
ibind\client\ibkr_utils.py                              226     42    81%   222, 310-313, 316, 440-441, 446, 603-606, 617-620, 639-642, 645-657, 666-672, 684-689
ibind\client\ibkr_ws_client.py                          238     65    73%   274, 277-281, 321, 326-328, 331, 351, 384, 390-394, 403-416, 422-423, 431-442, 447-460, 480, 484, 488, 491, 504, 517, 535, 538, 551, 702-714
ibind\oauth\__init__.py                                  26     26     0%   1-58
ibind\oauth\oauth1a.py                                  164    164     0%   1-466
ibind\support\__init__.py                                 0      0   100%
ibind\support\errors.py                                   4      0   100%
ibind\support\logs.py                                    82     57    30%   20-29, 75-96, 121-141, 150-153, 156-157, 160, 163-168, 171-175
ibind\support\py_utils.py                                87     25    71%   143, 153-156, 169, 308, 324-332, 336-354
ibind\var.py                                             88      4    95%   24-25, 36-37
-----------------------------------------------------------------------------------
TOTAL                                                  1730    612    65%

Pytest coverage:

---------- coverage: platform win32, python 3.13.11-final-0 ----------
Name                                                  Stmts   Miss  Cover   Missing
-----------------------------------------------------------------------------------
ibind\__init__.py                                        13      0   100%
ibind\base\__init__.py                                    0      0   100%
ibind\base\queue_controller.py                           18      0   100%
ibind\base\rest_client.py                               152     35    77%   103, 110, 235, 240, 252, 265-275, 280-284, 296-297, 306-308, 311, 334-337, 340-346, 355
ibind\base\subscription_controller.py                   125     33    74%   65, 67-69, 74-75, 86, 89, 92, 100-101, 154, 173-191, 211, 283, 286, 289-292, 326, 334, 358
ibind\base\ws_client.py                                 217     38    82%   64, 90, 95, 118-120, 124-129, 151, 155-156, 168-169, 190, 196-198, 202-204, 238, 247, 254-256, 317-322, 363, 439-440, 457, 470
ibind\client\__init__.py                                  0      0   100%
ibind\client\ibkr_client.py                             119     69    42%   87-91, 116-119, 132-135, 143-149, 163-164, 195-218, 234-237, 250-251, 254-256, 265-267, 270-272, 286, 289-333
ibind\client\ibkr_client_mixins\__init__.py               0      0   100%
ibind\client\ibkr_client_mixins\accounts_mixin.py         4      0   100%
ibind\client\ibkr_client_mixins\contract_mixin.py        25      0   100%
ibind\client\ibkr_client_mixins\marketdata_mixin.py      61     28    54%   54-85, 226, 236-241
ibind\client\ibkr_client_mixins\order_mixin.py           22     12    45%   102-110, 175-183
ibind\client\ibkr_client_mixins\portfolio_mixin.py        5      0   100%
ibind\client\ibkr_client_mixins\scanner_mixin.py          5      0   100%
ibind\client\ibkr_client_mixins\session_mixin.py         39     13    67%   105, 130-145
ibind\client\ibkr_client_mixins\watchlist_mixin.py        4      0   100%
ibind\client\ibkr_definitions.py                          6      0   100%
ibind\client\ibkr_utils.py                              226     42    81%   222, 310-313, 316, 440-441, 446, 603-606, 617-620, 639-642, 645-657, 666-672, 684-689
ibind\client\ibkr_ws_client.py                          238     65    73%   274, 277-281, 321, 326-328, 331, 351, 384, 390-394, 403-416, 422-423, 431-442, 447-460, 480, 484, 488, 491, 504, 517, 535, 538, 551, 702-714
ibind\oauth\__init__.py                                  26     26     0%   1-58
ibind\oauth\oauth1a.py                                  164    164     0%   1-466
ibind\support\__init__.py                                 0      0   100%
ibind\support\errors.py                                   4      0   100%
ibind\support\logs.py                                    82     13    84%   23-29, 94, 96, 136, 143, 164, 172-173
ibind\support\py_utils.py                                87     25    71%   143, 153-156, 169, 308, 324-332, 336-354
ibind\var.py                                             88      4    95%   24-25, 36-37
-----------------------------------------------------------------------------------
TOTAL                                                  1730    567    67%

google-labs-jules bot and others added 30 commits December 21, 2025 10:17
This change creates a detailed migration plan to convert all existing
unittest-based tests to pytest. The plan is structured into chunks to
allow for parallel work by multiple AI agents.

The plan is located in `test/migration_plan.md` and includes:
- A method for identifying all unittest files.
- General guidelines for the migration.
- A file-by-file breakdown with specific migration steps and potential
  challenges.
This change creates a detailed migration plan to convert all existing
unittest-based tests to pytest. The plan is structured into chunks to
allow for parallel work.

The plan is located in `test/migration_plan.md` and includes:
- A method for identifying all unittest files.
- General guidelines for the migration.
- A file-by-file breakdown with specific migration steps and potential
  challenges.
This change creates a comprehensive, file-by-file migration plan to convert all existing unittest-based tests to pytest. The plan is structured into individually actionable chunks.

The plan is located in `test/migration_plan.md` and includes:
- General guidelines for the migration.
- A detailed analysis of each unittest file.
- Specific migration steps and potential challenges for each file.
Adds a new pytest-friendly test utility file at `test/test_utils_new.py`. This file includes the `capture_logs` context manager and decorator for advanced log testing.

Creates a detailed migration plan in `test/migration_plan.md` to guide the conversion of all existing unittest files to pytest. The plan instructs developers to create new test files for side-by-side comparison and to use the new utilities.
Adds a new pytest-friendly test utility file at `test/test_utils_new.py`. This file includes the `capture_logs` context manager and decorator for advanced log testing.

Creates a detailed migration plan in `test/migration_plan.md` to guide the conversion of all existing unittest files to pytest. The plan instructs developers to create new test files for side-by-side comparison and to use the new utilities.
Adds a new pytest-friendly test utility file at `test/test_utils_new.py`. This file includes the `capture_logs` context manager and decorator for advanced log testing.

Creates a detailed migration plan in `test/migration_plan.md` to guide the conversion of all existing unittest files to pytest. The plan instructs developers to create new test files for side-by-side comparison and to use the new utilities.
Adds a new pytest-friendly test utility file at `test/test_utils_new.py`. This file includes the `capture_logs` context manager and decorator for advanced log testing, along with other test helpers.

Creates a detailed migration plan in `test/migration_plan.md` to guide the conversion of all existing unittest files to pytest. The plan instructs developers to create new test files for side-by-side comparison and to use the new utilities.
Adds a new pytest-friendly test utility file at `test/test_utils_new.py`. This file includes the `capture_logs` context manager and decorator for advanced log testing, along with other test helpers.

Moves the `get_logger_children` function from the test utilities to `ibind/support/logs.py` to make it a general-purpose utility.

Creates a detailed migration plan in `test/migration_plan.md` to guide the conversion of all existing unittest files to pytest. The plan instructs developers to create new test files for side-by-side comparison and to use the new utilities.
Feat: Create unittest to pytest migration plan
Migrated the unittest-based tests in test/integration/base/test_rest_client_i.py to pytest-style tests in a new file, test/integration/base/test_rest_client_i_new.py.

This migration includes:
- Converting unittest.TestCase to pytest test functions.
- Replacing setUp with pytest fixtures.
- Replacing unittest assertions with pytest assertions.
- Using the mocker fixture for patching.
- Using the CaptureLogsContext for logging assertions.

Also includes a defensive fix to test/test_utils_new.py to handle a TypeError when calling the make_clean_stack function.
Migrated the unittest-based tests in test/integration/base/test_rest_client_i.py to pytest-style tests in a new file, test/integration/base/test_rest_client_i_new.py.

This migration includes:
- Converting unittest.TestCase to pytest test functions.
- Replacing setUp with pytest fixtures.
- Replacing unittest assertions with pytest assertions.
- Using the mocker fixture for patching.
- Using the CaptureLogsContext for logging assertions.

Added ## Arrange, ## Act, and ## Assert comments to all tests in the new file to improve readability.

Split the `test_default_rest` function into three separate tests for better test isolation.

Includes a defensive fix to test/test_utils_new.py to handle a TypeError when calling the make_clean_stack function.
Migrated the unittest-based tests in test/integration/base/test_rest_client_i.py to pytest-style tests in a new file, test/integration/base/test_rest_client_i_new.py.

This migration includes:
- Converting unittest.TestCase to pytest test functions.
- Replacing setUp with pytest fixtures.
- Replacing unittest assertions with pytest assertions.
- Using the mocker fixture for patching.
- Using the CaptureLogsContext for logging assertions.

Improved test readability by:
- Adding ## Arrange, ## Act, and ## Assert comments to all tests.
- Splitting the `test_default_rest` function into three separate tests for better test isolation.

Also includes a defensive fix to test/test_utils_new.py to handle a TypeError when calling the make_clean_stack function.
Split tuple fixtures into constants + granular fixtures; add autouse requests_mock with default return_value to reduce boilerplate in migrated tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants