Skip to content

Release 1.3.0: 1.2.7 bug fixes and minor features - #119

Merged
alvarolaserna merged 3 commits into
testdevlab:masterfrom
ErnestsS-TDL:1.2.7-minor-bugfix
Oct 8, 2026
Merged

alvarolaserna merged 3 commits into
testdevlab:masterfrom
ErnestsS-TDL:1.2.7-minor-bugfix

Conversation

@ErnestsS-TDL

@ErnestsS-TDL ErnestsS-TDL commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

This release combines the 1.2.7 bug fixes with the 1.3.0 features. It fixes 24 bugs and adds iOS parallel device assignment, custom Appium arguments and more image matching options. Each fix changes code that currently crashes, hangs or has no effect, and the new features are opt-in. The only exception is the get_middle_point() return type (see Breaking change).

It changes no dependencies, Python versions or CI. Those changes come in the next major release, together with a migration guide.

Scope: 7 files under testui/ change (435 lines added, 339 removed), plus the integration test. The package version in setup.py and README.md goes from 1.2.6 to 1.3.0.

Breaking change

  • ImageRecognition.get_middle_point() returns the (x, y) point. It used to run the match and return self, so the point it found was never returned. Code that chains on it, such as .get_middle_point().draw_image_match(), needs updating.

1.2.7 – Bug fixes

Driver setup

  • Parallel mobile runs no longer crash on startup. Under pytest-xdist, every local Appium run (Android and iOS) failed with a TypeError, because the worker index was added to an int as a string.
  • Appium startup no longer waits forever. If Appium crashed or never became ready, the test hung until CI killed the job. Startup now fails as soon as the Appium process exits. Otherwise it fails after 120 seconds; you can raise that limit with appium_driver.APPIUM_START_TIMEOUT. Attaching to a server that is already running on the port works as before. The two copies of the wait loop are now one function.
  • iOS connects to Appium 3. The iOS launcher checked for the version with startswith("2."), so Appium 3 got the legacy /wd/hub URL and the session failed. Both platforms now use the same major-version check.
  • appium -v runs once per process. It used to start Node.js on every session just to print the version. The result is now cached.
  • Removed a lock that locked nothing. start_driver created a new lock on every call, so it never synchronized anything, and it was never released if an exception occurred.
  • Safari, Edge and IE launch again. They passed constructor arguments that Selenium removed in 4.10, so they raised TypeError on every Selenium version TestUI can install. Each browser now gets its own Options object, as Chrome and Firefox already do. webdriver.Opera no longer exists in Selenium, so Opera now raises a clear error.
  • Removed capabilities the driver ignores. appium:chromeDriverPort has the wrong casing, and appium:androidInstallPath isn't a UiAutomator2 capability, so the driver ignored both. They were deleted rather than renamed, so Chrome ports stay unpinned as they are today.
  • Fixed the chromedriver lookup on macOS. An and/or precedence bug matched mac_arm64 entries on every OS, and Intel Macs were detected as Apple Silicon. This only affects the legacy lookup for Chrome 114 and older.

Elements and collections

  • execute_script works without arguments. execute_script("return 1") raised TypeError, because args had no default. Calls that already worked send the same arguments to Selenium. Scripts with several arguments now also work: execute_script(script, a, b).
  • swipe_until_text checks the right arguments. It checked start_x instead of end_x, so valid calls were rejected and calls with no end point got through. When no element is given, it now requires both end_x and end_y.
  • swipe_until_text swipes in soft-assert mode. It never swiped in soft mode and recorded a false error. In hard mode it took a screenshot and added an error on every probe. It now probes without asserting and checks once more after the last swipe. The log says "not found" only when the text was never found. It still returns the element.
  • find_by_attribute(case_sensitive=False) handles a missing attribute. It crashed when an element didn't have the attribute. A missing attribute now counts as an empty string.
  • Collection waits are judged by their results. wait_until_all_visible, wait_until_all_exist and wait_until_attribute decided pass or fail by elapsed time. So a collection that was fully found, just slowly, was reported as a failure, and errors from threads were lost. They now check what each wait found and include the details in the failure message. The error list is also cleared on each call. Every failure reported before is still reported; only false failures go away.
  • Polling loops pause between requests. is_visible_in, find_visible, find_by_attribute and the three attribute waits sent requests back to back and flooded Appium. They now pause 0.2 seconds between polls. Timeouts are unchanged, and a success is noticed at most 0.2 seconds later.
  • visible_for no longer logs on every poll. It wrote hundreds of log lines per second. The final result is still logged.
  • location and dimensions look up the element once. Each did two element lookups, so slide_percentage did six.

Driver wrapper and screenshots

  • Recorded videos are saved to the right path. stop_recording_and_compare joined the screenshot path twice, which broke relative paths.
  • The element screenshot crop fallback works. It passed an already-joined path that was joined to ./logs again, so with the default configuration it always crashed.
  • The deprecated decorator keeps the function name. Deprecated functions showed up as wrapper in help text and stack traces.

Image matching

  • No more races, CPU spin or mixed-up results. Results were kept in module-level globals. While waiting, the main thread spun at 100% CPU. Threads left over from one comparison could write into the next one, so two devices comparing at the same time could corrupt each other's results. Each comparison now has its own state and waits on an event. The scale grid and default color mode are unchanged, so matches are found or not found exactly as before.
  • A template larger than the screenshot returns (False, 0.0). It used to raise ValueError: max() iterable argument is empty.

Parallel runner and TestRail

  • TestRail run creation works without --single_thread_marker. The marker expression ended in or, so pytest rejected it.
  • The TestRail process is stopped on failure. send_signal(signal=2) raised TypeError. The call was removed, and terminate() already stops the process.
  • The pass percentage no longer divides by zero. When no markers deselected tests, the test count was 0, and the failure summary crashed instead of reporting the failures.
  • The TestRail password is masked in logs. The full pytest command, including --tr-password, was written to the console and the log file. The command that runs is unchanged.

1.3.0 – Features and fixes

Appium and devices

  • Parallel iOS runs use separate devices. Under pytest-xdist, each worker gets its own device: connected real devices first (devicectl), then booted simulators (simctl). Each worker also gets its own wdaLocalPort and mjpegServerPort, so sessions don't share WebDriverAgent. Without xdist, Appium chooses the device as before.
  • set_appium_args() passes extra arguments to a locally started Appium server. The session URL follows --base-path (or -pa) when it's given. Otherwise it uses the version default as before.
  • Startup also checks Appium's /status endpoint. This catches a ready server even when the log text doesn't match. The check bypasses HTTP(S)_PROXY.
  • set_isolated_configuration() gives a driver its own copy of the configuration. By default, all drivers still share one.
  • Context switching uses switch_to.context, and there's a new current_context property.

Image matching

  • compare(grayscale=True) matches in grayscale. It's faster, but scores differ from color. The saved match image is still drawn in color.
  • get_point_match and click_by_image report weak matches. A best match below the threshold logs a warning and is still used. Pass strict=True to raise an error instead. A template larger than the screenshot raises a clear error instead of TypeError.
  • Image paths are looked up the same way everywhere. Every ImageRecognition method looks for files as given, then under path, and raises "There is no image in …" if neither exists. Before, get_middle_point, draw_image_match and the size and crop methods ignored path or crashed with a NoneType error.
  • click_by_image clicks once. It clicked twice, so toggles and "next" buttons were pressed twice. The screenshot is now deleted even when matching or clicking fails.

Integration test

  • test_template_matching passes again (it failed on master too).
    • GitHub's scroll to the anchor is animated and was still running when the screenshot was taken. The test now waits for the README heading and jumps straight to it.
    • It forces the light color scheme, because the README diagram has a transparent background.
    • testdevlab.com renamed its email field to #emailaddress.

Verification

  • Mock-driver tests (not part of this PR) cover the 1.2.7 fixes. On the original code, 9 of the 11 tests fail.
  • Image matching gives the same results as before on matching and non-matching images.
  • The Selenium integration tests pass locally in headless Chrome, 5 out of 5 runs.
  • pylint, with the project's config, scores 8.43 before this change and 8.53 after (local run on Python 3.14; CI numbers may differ).
  • Not tested here: real devices, iOS parallel runs, a live Appium server with --base-path, browsers other than Chrome, and Windows.

@ErnestsS-TDL ErnestsS-TDL changed the title Release 1.2.7 with minor bug fixes Release 1.3.0: 1.2.7 bug fixes and minor features Oct 7, 2026
@alvarolaserna
alvarolaserna merged commit d2b9ed1 into testdevlab:master Oct 8, 2026
5 checks passed
@ErnestsS-TDL
ErnestsS-TDL deleted the 1.2.7-minor-bugfix branch October 8, 2026 11:43
@ErnestsS-TDL
ErnestsS-TDL restored the 1.2.7-minor-bugfix branch October 8, 2026 11:44
@ErnestsS-TDL
ErnestsS-TDL deleted the 1.2.7-minor-bugfix branch October 8, 2026 11:45
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