Skip to content

Commit

Permalink
add more unittests
Browse files Browse the repository at this point in the history
  • Loading branch information
codeskyblue committed Jul 14, 2024
1 parent 1af2d4c commit c189745
Show file tree
Hide file tree
Showing 22 changed files with 538 additions and 122 deletions.
8 changes: 6 additions & 2 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
branch = True

omit =
"tests/*"
"docs/*"
/tests/**
/docs/*
/*_tests/**

[report]
; Regexes for lines to exclude from consideration
Expand All @@ -23,4 +24,7 @@ exclude_also =
; Don't complain about abstract methods, they aren't run:
@(abc\.)?abstractmethod

except adbutils.AdbError
@deprecated

ignore_errors = True
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ format:
test:
poetry run pytest -v mobile_tests/

covtest:
poetry run coverage run -m pytest -v demo_tests tests
poetry run coverage html --include 'uiautomator2/**'


cov:
poetry run pytest -v tests/ \
--cov-config=.coveragerc \
Expand Down
19 changes: 19 additions & 0 deletions demo_tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# coding: utf-8
# author: codeskyblue

import pytest
import uiautomator2 as u2


@pytest.fixture(scope="function")
def d():
_d = u2.connect_usb()
_d.press("home")
yield _d


@pytest.fixture(scope="function")
def app(d: u2.Device):
d.app_start("com.example.u2testdemo", stop=True)
d(text="Addition").wait()
yield d
57 changes: 57 additions & 0 deletions demo_tests/test_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# coding: utf-8
# author: codeskyblue

import pytest
import uiautomator2 as u2


PACKAGE = "com.example.u2testdemo"


def test_wait_activity(d: u2.Device):
# assert app.wait_activity('.MainActivity', timeout=10)

d.app_start(PACKAGE, activity=".AdditionActivity", wait=True)
assert d.wait_activity('.AdditionActivity', timeout=3)
assert not d.wait_activity('.NotExistActivity', timeout=1)


def test_app_wait(app: u2.Device):
assert app.app_wait(PACKAGE, front=True)


def test_app_start_stop(d: u2.Device):
assert PACKAGE in d.app_list()
d.app_stop(PACKAGE)
assert PACKAGE not in d.app_list_running()
d.app_start(PACKAGE, wait=True)
assert PACKAGE in d.app_list_running()


def test_app_clear(d: u2.Device):
d.app_clear(PACKAGE)
# d.app_stop_all()


def test_app_info(d: u2.Device):
d.app_info(PACKAGE)
with pytest.raises(u2.AppNotFoundError):
d.app_info("not.exist.package")


def test_auto_grant_permissions(d: u2.Device):
d.app_auto_grant_permissions(PACKAGE)


def test_session(d: u2.Device):
app = d.session(PACKAGE)
assert app.running() is True
assert app.pid > 0
old_pid = app.pid

app.restart()
assert old_pid != app.pid

with app:
app(text="Addition").info

131 changes: 131 additions & 0 deletions demo_tests/test_device.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# coding: utf-8
# author: codeskyblue

from pathlib import Path
import random
import pytest
import uiautomator2 as u2
from PIL import Image


def test_info(d: u2.Device):
d.info
d.device_info
d.wlan_ip
assert isinstance(d.serial, str)

w, h = d.window_size()
assert w > 0 and h > 0


def test_dump_hierarchy(d: u2.Device):
assert d.dump_hierarchy().startswith("<?xml")
assert d.dump_hierarchy(compressed=True, pretty=True).startswith("<?xml")


def test_screenshot(d: u2.Device, tmp_path: Path):
im = d.screenshot()
assert isinstance(im, Image.Image)

d.screenshot(tmp_path / "screenshot.png")
assert (tmp_path / "screenshot.png").exists()


def test_settings(d: u2.Device):
d.implicitly_wait(10)


def test_click(app: u2.Device):
app.click(1, 1)
app.long_click(1, 1)
app.click(0.5, 0.5)
app.double_click(1, 1)


def test_swipe_drag(app: u2.Device):
app.swipe(1, 1, 2, 2, steps=20)
app.swipe(1, 1, 2, 2, duration=.1)
app.swipe(1, 1, 2, 2)
with pytest.warns(UserWarning):
app.swipe(1, 1, 2, 2, 0.1, 20)

app.swipe_points([(1, 1), (2, 2)], duration=0.1)
app.drag(1, 1, 2, 2, duration=0.1)


@pytest.mark.parametrize("direction", ["up", "down", "left", "right"])
def test_swipe_ext(d: u2.Device, direction: str):
d.swipe_ext(direction)


def test_swipe_ext_inside_box(app: u2.Device):
bounds = app.xpath('@android:id/content').get().bounds
app.swipe_ext("up", box=bounds)


def test_press(d: u2.Device):
d.press("volume_down")
# press home keycode
d.press(3)

d.long_press("volume_down")
# long volume_down keycode
d.long_press(25)

d.keyevent("volume_down")


def test_screen(d: u2.Device):
# d.screen_off()
d.screen_on()


def test_orientation(d: u2.Device):
with pytest.raises(ValueError):
d.orientation = 'unknown'

d.orientation = 'n'
assert d.orientation == 'natural'
d.freeze_rotation(True)
d.freeze_rotation(False)


def test_traversed_text(d: u2.Device):
d.last_traversed_text
d.clear_traversed_text()


def test_open(d: u2.Device):
d.open_notification()
d.open_quick_settings()
d.open_url("https://www.baidu.com")


def test_toast(app: u2.Device):
app.clear_toast()
assert app.last_toast is None

app(text='Toast').click()
app(text='Show Toast').click()
app.sleep(.2)
assert app.last_toast == "Button Clicked!"

app.clear_toast()
assert app.last_toast is None


def test_clipboard(d: u2.Device):
d.set_input_ime()
text = str(random.randint(0, 1000))
d.clipboard = f'n{text}'
assert d.clipboard == f'n{text}'


def test_push_pull(d: u2.Device, tmp_path: Path):
src_file = tmp_path / "test_push.txt"
src_file.write_text("12345")
d.push(src_file, "/data/local/tmp/test_push.txt")

dst_file = tmp_path / "test_pull.txt"
d.pull("/data/local/tmp/test_push.txt", dst_file)
assert dst_file.read_text() == "12345"
37 changes: 37 additions & 0 deletions demo_tests/test_input.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# coding: utf-8
# author: codeskyblue

import pytest
import uiautomator2 as u2


def test_set_ime(d: u2.Device):
d.set_input_ime(True)
d.set_input_ime(False)


def test_send_keys(app: u2.Device):
app(text="Addition").click()
num1 = app(className="android.widget.EditText", instance=0)
num2 = app(className="android.widget.EditText", instance=1)
result = app(className="android.widget.EditText", instance=2)

num1.set_text("5")
assert num1.get_text() == "5"
num1.clear_text()
assert num1.get_text() == ''
num1.set_text('1')

num2.click()
app.send_keys('6')
assert num2.get_text() == '6'
app.clear_text()
app.send_keys('2')

app(text="Add").click()
result = app(className="android.widget.EditText", instance=2).get_text()
assert result == "3"


def test_send_action(): # TODO
pass
89 changes: 89 additions & 0 deletions demo_tests/test_selector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# coding: utf-8
# author: codeskyblue

import time
import pytest
import uiautomator2 as u2
from uiautomator2 import Selector

def test_selector_magic():
s = Selector(text='123').child(text='456').sibling(text='789').clone()
assert s['text'] == '123'
del s['text']
assert 'text' not in s
s.update_instance(0)


def test_exists(app: u2.Device):
assert app(text='Addition').exists
assert app(text='Addition').exists(timeout=.1)
assert not app(text='should-not-exists').exists
assert not app(text='should-not-exists').exists(timeout=.1)


def test_selector_info(app: u2.Device):
_info = app(text="Addition").info
assert _info["text"] == "Addition"


@pytest.mark.skip(reason="not stable")
def test_child_by(app: u2.Device):
app(text="Addition").click()
app(text='Add').wait()
time.sleep(.5)
# childByText, childByInstance and childByDescription run query when called
app(resourceId='android:id/content').child_by_text("Add")
app(resourceId='android:id/content').child_by_instance(0)
with pytest.raises(u2.UiObjectNotFoundError):
app(resourceId='android:id/content').child_by_description("should-not-exists")

# only run query after call UiObject method
assert app(resourceId='android:id/content').child_selector(text="Add").exists


def test_screenshot(app: u2.Device):
lx, ly, rx, ry = app(text="Addition").bounds()
image = app(text="Addition").screenshot()
assert image.size == (rx - lx, ry - ly)


def test_center(app: u2.Device):
x, y = app(text="Addition").center()
assert x > 0 and y > 0


def test_click_exists(app: u2.Device):
assert app(text="Addition").click_exists()
app(text='Addition').wait_gone()
assert not app(text="should-not-exists").click_exists()


@pytest.mark.parametrize("direction", ["up", "down", "left", "right"])
def test_swipe(app: u2.Device, direction: str):
app(resourceId="android:id/content").swipe(direction)


def test_pinch_gesture(app: u2.Device):
app(text='Pinch').click()
app(description='pinch image').wait()
scale_text = app.xpath('Scale%').get_text()
assert scale_text.endswith('1.00')

app(description='pinch image').pinch_in(80)
scale_text = app.xpath('Scale%').get_text()
assert scale_text.endswith('0.50')

app(description='pinch image').pinch_out()
scale_text = app.xpath('Scale%').get_text()
assert scale_text.endswith('3.00')

app().gesture((0.1, 0.5), (0.9, 0.5), (0.5, 0.5), (0.5, 0.5), steps=20)
scale_text = app.xpath('Scale%').get_text()
assert scale_text.endswith('0.50')


# TODO
# long_click
# drag_to
# swipe
# guesture
Loading

0 comments on commit c189745

Please sign in to comment.