Repository navigation
Release 1.3.0: 1.2.7 bug fixes and minor features - #119
Merged
Merged
Conversation
alvarolaserna
approved these changes
Oct 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 insetup.pyandREADME.mdgoes 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 returnself, 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
TypeError, because the worker index was added to an int as a string.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.startswith("2."), so Appium 3 got the legacy/wd/hubURL and the session failed. Both platforms now use the same major-version check.appium -vruns once per process. It used to start Node.js on every session just to print the version. The result is now cached.start_drivercreated a new lock on every call, so it never synchronized anything, and it was never released if an exception occurred.TypeErroron every Selenium version TestUI can install. Each browser now gets its ownOptionsobject, as Chrome and Firefox already do.webdriver.Operano longer exists in Selenium, so Opera now raises a clear error.appium:chromeDriverPorthas the wrong casing, andappium:androidInstallPathisn't a UiAutomator2 capability, so the driver ignored both. They were deleted rather than renamed, so Chrome ports stay unpinned as they are today.and/orprecedence bug matchedmac_arm64entries 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_scriptworks without arguments.execute_script("return 1")raisedTypeError, becauseargshad 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_textchecks the right arguments. It checkedstart_xinstead ofend_x, so valid calls were rejected and calls with no end point got through. When no element is given, it now requires bothend_xandend_y.swipe_until_textswipes 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.wait_until_all_visible,wait_until_all_existandwait_until_attributedecided 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.is_visible_in,find_visible,find_by_attributeand 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_forno longer logs on every poll. It wrote hundreds of log lines per second. The final result is still logged.locationanddimensionslook up the element once. Each did two element lookups, soslide_percentagedid six.Driver wrapper and screenshots
stop_recording_and_comparejoined the screenshot path twice, which broke relative paths../logsagain, so with the default configuration it always crashed.deprecateddecorator keeps the function name. Deprecated functions showed up aswrapperin help text and stack traces.Image matching
(False, 0.0). It used to raiseValueError: max() iterable argument is empty.Parallel runner and TestRail
--single_thread_marker. The marker expression ended inor, so pytest rejected it.send_signal(signal=2)raisedTypeError. The call was removed, andterminate()already stops the process.--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
devicectl), then booted simulators (simctl). Each worker also gets its ownwdaLocalPortandmjpegServerPort, 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./statusendpoint. This catches a ready server even when the log text doesn't match. The check bypassesHTTP(S)_PROXY.set_isolated_configuration()gives a driver its own copy of the configuration. By default, all drivers still share one.switch_to.context, and there's a newcurrent_contextproperty.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_matchandclick_by_imagereport weak matches. A best match below the threshold logs a warning and is still used. Passstrict=Trueto raise an error instead. A template larger than the screenshot raises a clear error instead ofTypeError.ImageRecognitionmethod looks for files as given, then underpath, and raises "There is no image in …" if neither exists. Before,get_middle_point,draw_image_matchand the size and crop methods ignoredpathor crashed with aNoneTypeerror.click_by_imageclicks 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_matchingpasses again (it failed onmastertoo).#emailaddress.Verification
--base-path, browsers other than Chrome, and Windows.