├── requirements.txt
├── .gitignore
├── README.md
├── tests
├── macaca-desktop-sample.test.py
├── macaca-ios-sample.test.py
└── macaca-android-sample.test.py
└── .travis.yml
/requirements.txt:
--------------------------------------------------------------------------------
1 | wd
2 | retrying
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea/*
3 | Thumbs.db
4 | coverage/
5 | .project
6 | build/
7 | macaca-logs/
8 | *.sw*
9 | *.un~
10 | *.png
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # sample-python
2 |
3 | ## CI Sample
4 |
5 | [![build status][travis-image-0]][travis-url-0]
6 |
7 | [travis-image-0]: https://img.shields.io/travis/macaca-sample/sample-python/master.svg?style=flat-square
8 | [travis-url-0]: https://travis-ci.org/macaca-sample/sample-python
9 |
10 | ## Install
11 |
12 | ``` bash
13 | $ npm install -g macaca-cli macaca-electron macaca-ios macaca-android
14 | $ pip install -r requirements.txt
15 | ```
16 |
17 | ## Run test
18 |
19 | ``` bash
20 | $ macaca server --verbose
21 | $ python tests/macaca-desktop-sample.test.py
22 | $ python tests/macaca-ios-sample.test.py
23 | $ python tests/macaca-android-sample.test.py
24 | ```
25 |
26 |
27 |
28 | ## Contributors
29 |
30 | |[
ziczhu](https://github.com/ziczhu)
|[
xudafeng](https://github.com/xudafeng)
31 | | :---: | :---: |
32 |
33 |
34 | This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto upated at `Tue Apr 17 2018 00:49:24 GMT+0800`.
35 |
36 |
37 |
38 | ## License
39 |
40 | The MIT License (MIT)
41 |
--------------------------------------------------------------------------------
/tests/macaca-desktop-sample.test.py:
--------------------------------------------------------------------------------
1 | #coding:utf-8
2 |
3 | import unittest
4 | import time
5 | from macaca import WebDriver
6 |
7 | desired_caps = {
8 | 'platformName': 'desktop',
9 | 'browserName': 'electron'
10 | }
11 |
12 | server_url = {
13 | 'hostname': 'localhost',
14 | 'port': 3456
15 | }
16 |
17 | class MacacaTest(unittest.TestCase):
18 | @classmethod
19 | def setUpClass(cls):
20 | cls.driver = WebDriver(desired_caps, server_url)
21 | cls.driver.init()
22 |
23 | @classmethod
24 | def tearDownClass(cls):
25 | cls.driver.quit()
26 |
27 | def test_get_url(self):
28 | self.driver \
29 | .set_window_size(1280, 800) \
30 | .get('https://www.baidu.com')
31 |
32 | def test_search_macaca(self):
33 | self.driver \
34 | .element_by_id('kw') \
35 | .send_keys('macaca')
36 | self.driver \
37 | .element_by_id('su') \
38 | .click()
39 | time.sleep(3)
40 | html = self.driver.source
41 | self.assertTrue('macaca' in html)
42 | self.assertTrue(
43 | self.driver.element_by_css_selector_if_exists(
44 | '#head > div.head_wrapper'))
45 | self.driver \
46 | .element_by_xpath_or_none('//*[@id="kw"]') \
47 | .send_keys(' elementByXPath')
48 | self.driver \
49 | .element_by_id('su') \
50 | .click()
51 | self.driver.take_screenshot()
52 |
53 |
54 | if __name__ == '__main__':
55 | unittest.main()
56 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | os:
2 | - osx
3 | - linux
4 | env:
5 | - TEST_SUITE=ios
6 | - TEST_SUITE=android
7 | - TEST_SUITE=pc-browser
8 | matrix:
9 | fast_finish: true
10 | exclude:
11 | - os: osx
12 | env: TEST_SUITE=ios
13 | - os: osx
14 | env: TEST_SUITE=android
15 | - os: osx
16 | env: TEST_SUITE=pc-browser
17 | - os: linux
18 | env: TEST_SUITE=ios
19 | - os: linux
20 | env: TEST_SUITE=android
21 | - os: linux
22 | env: TEST_SUITE=pc-browser
23 | include:
24 | - os: osx
25 | env: TEST_SUITE=ios
26 | osx_image: xcode9
27 | language: generic
28 | before_install:
29 | - brew update
30 | - brew install carthage > /dev/null 2>&1
31 | - brew install ios-webkit-debug-proxy > /dev/null 2>&1
32 | - brew install nvm > /dev/null 2>&1
33 | - brew install python3
34 | - pip install virtualenv
35 | - virtualenv env -p python3
36 | - source env/bin/activate
37 | install:
38 | - echo Hello Macaca!
39 | - source $(brew --prefix nvm)/nvm.sh
40 | - nvm install 7
41 | - nvm use 7
42 | - npm i ios-simulator macaca-cli macaca-ios -g
43 | - open -a Simulator --args -CurrentDeviceUDID `ios-simulator -n 'iPhone 6s'` > /dev/null 2>&1
44 | - pip install -r requirements.txt
45 | script:
46 | - macaca server --verbose &
47 | - sleep 10
48 | - python tests/macaca-ios-sample.test.py
49 | - os: linux
50 | env: TEST_SUITE=android
51 | jdk: oraclejdk8
52 | language: android
53 | android:
54 | components:
55 | - tools
56 | - build-tools-25.0.2
57 | - platform-tools
58 | - extra-android-m2repository
59 | - extra-google-android-support
60 | - android-25
61 | sudo: required
62 | addons:
63 | apt:
64 | sources:
65 | - deadsnakes
66 | packages:
67 | - python3.5
68 | before_install:
69 | - export CHROME_BIN=chromium-browser
70 | - wget http://services.gradle.org/distributions/gradle-3.3-all.zip
71 | - unzip gradle-3.3-all.zip > /dev/null
72 | - export GRADLE_HOME=$PWD/gradle-3.3
73 | - export PATH=$GRADLE_HOME/bin:$PATH
74 | - export JAVA_HOME=/usr/lib/jvm/java-8-oracle
75 | - export ANDROID_HOME=/usr/local/android-sdk
76 | - . $HOME/.nvm/nvm.sh
77 | - export DISPLAY=:99.0
78 | - sh -e /etc/init.d/xvfb start
79 | before_script:
80 | - echo no | android create avd --force -n test -t android-21 --abi armeabi-v7a
81 | - emulator -avd test -no-audio -no-window &
82 | - android-wait-for-emulator
83 | - adb shell input keyevent 82 &
84 | install:
85 | - echo Hello Macaca!
86 | - nvm install 7
87 | - nvm use 7
88 | - npm install -g macaca-cli macaca-android
89 | - pip install virtualenv
90 | - virtualenv env -p python3.5
91 | - source env/bin/activate
92 | - pip install -r requirements.txt
93 | script:
94 | - macaca server --verbose &
95 | - sleep 10
96 | - python3 tests/macaca-android-sample.test.py
97 | - os: linux
98 | env:
99 | - TEST_SUITE=pc-browser
100 | language: python
101 | sudo: false
102 | python: 3.5
103 | addons:
104 | apt:
105 | packages:
106 | - xvfb
107 | before_install:
108 | - . $HOME/.nvm/nvm.sh
109 | - export DISPLAY=':99.0'
110 | - Xvfb :99 -screen 0 1366x768x24 > /dev/null 2>&1 &
111 | install:
112 | - echo Hello Macaca!
113 | - nvm install 7
114 | - nvm use 7
115 | - npm install -g macaca-cli macaca-electron
116 | - pip install -r requirements.txt
117 | script:
118 | - macaca server --verbose &
119 | - sleep 10
120 | - python3 tests/macaca-desktop-sample.test.py
121 |
--------------------------------------------------------------------------------
/tests/macaca-ios-sample.test.py:
--------------------------------------------------------------------------------
1 | #coding:utf-8
2 |
3 | import unittest
4 | import os
5 | import time
6 | from macaca import WebDriver
7 | from retrying import retry
8 |
9 | desired_caps = {
10 | 'platformName': 'iOS',
11 | 'deviceName': 'iPhone 6s',
12 | 'app': 'https://npmcdn.com/ios-app-bootstrap@latest/build/ios-app-bootstrap.zip',
13 | }
14 |
15 |
16 | server_url = {
17 | 'hostname': 'localhost',
18 | 'port': 3456
19 | }
20 |
21 | def switch_to_webview(driver):
22 | contexts = driver.contexts
23 | driver.context = contexts[-1]
24 | return driver
25 |
26 | def switch_to_native(driver):
27 | contexts = driver.contexts
28 | driver.context = contexts[0]
29 | return driver
30 |
31 | class MacacaTest(unittest.TestCase):
32 | @classmethod
33 | def setUpClass(cls):
34 | cls.driver = WebDriver(desired_caps, server_url)
35 | cls.initDriver()
36 |
37 | @classmethod
38 | def tearDownClass(cls):
39 | cls.driver.quit()
40 |
41 | @classmethod
42 | @retry
43 | def initDriver(cls):
44 | print("Retry connecting server...")
45 | cls.driver.init()
46 |
47 | def test_01_login(self):
48 | self.driver \
49 | .element_by_xpath('//XCUIElementTypeTextField[1]') \
50 | .send_keys('中文+Test+12345678') \
51 |
52 | self.driver \
53 | .element_by_xpath('//XCUIElementTypeSecureTextField[1]') \
54 | .send_keys('111111') \
55 |
56 | time.sleep(1)
57 |
58 | self.driver \
59 | .send_keys('\n')
60 |
61 | self.driver \
62 | .element_by_name('Login') \
63 | .click()
64 |
65 | def test_02_scroll_tableview(self):
66 | self.driver \
67 | .element_by_name('HOME') \
68 | .click()
69 |
70 | self.driver \
71 | .element_by_name('list') \
72 | .click()
73 |
74 | def test_03_gesture(self):
75 | self.driver \
76 | .touch('drag', {
77 | 'fromX': 200,
78 | 'fromY': 400,
79 | 'toX': 200,
80 | 'toY': 100,
81 | 'duration': 2
82 | })
83 |
84 | time.sleep(1)
85 |
86 | self.driver \
87 | .touch('drag', {
88 | 'fromX': 100,
89 | 'fromY': 100,
90 | 'toX': 100,
91 | 'toY': 400,
92 | 'duration': 2
93 | })
94 |
95 | time.sleep(1)
96 |
97 | self.driver \
98 | .element_by_name('Gesture') \
99 | .click()
100 |
101 | self.driver \
102 | .touch('tap', {
103 | 'x': 100,
104 | 'y': 100
105 | })
106 |
107 | time.sleep(1)
108 |
109 | self.driver \
110 | .touch('press', {
111 | 'x': 100,
112 | 'y': 100,
113 | 'duration': 1
114 | })
115 |
116 | time.sleep(1)
117 |
118 | self.driver \
119 | .element_by_id('info') \
120 | .touch('pinch', {
121 | 'scale': 2,
122 | 'velocity': 1
123 | })
124 |
125 | time.sleep(1)
126 |
127 | self.driver \
128 | .touch('drag', {
129 | 'fromX': 100,
130 | 'fromY': 100,
131 | 'toX': 100,
132 | 'toY': 600,
133 | 'steps': 100
134 | })
135 |
136 | def test_04_webview(self):
137 | self.driver \
138 | .element_by_name('Webview') \
139 | .click()
140 |
141 | time.sleep(3)
142 | self.driver.save_screenshot('./webView.png') # save screen shot
143 |
144 | switch_to_webview(self.driver) \
145 | .element_by_id('pushView') \
146 | .touch('tap')
147 |
148 | switch_to_webview(self.driver) \
149 | .element_by_id('popView') \
150 | .touch('tap')
151 |
152 | def test_05_web(self):
153 | switch_to_native(self.driver) \
154 | .element_by_name('Baidu') \
155 | .touch('tap')
156 |
157 | time.sleep(3)
158 | self.driver.save_screenshot("./baidu.png")
159 |
160 | switch_to_webview(self.driver) \
161 | .element_by_id('index-kw') \
162 | .send_keys('macaca') \
163 | .element_by_id('index-bn') \
164 | .touch('tap')
165 |
166 | def test_06_logout(self):
167 | switch_to_native(self.driver) \
168 | .element_by_name('PERSONAL') \
169 | .click()
170 |
171 | self.driver.element_by_name('Logout') \
172 | .click()
173 |
174 | if __name__ == '__main__':
175 | unittest.main()
176 |
--------------------------------------------------------------------------------
/tests/macaca-android-sample.test.py:
--------------------------------------------------------------------------------
1 | #coding:utf-8
2 |
3 | import unittest
4 | import os
5 | import time
6 | from macaca import WebDriver
7 | from macaca import Keys
8 | from retrying import retry
9 |
10 | desired_caps = {
11 | 'platformName': 'android',
12 | 'app': 'https://npmcdn.com/android-app-bootstrap@latest/android_app_bootstrap/build/outputs/apk/android_app_bootstrap-debug.apk',
13 | }
14 |
15 | server_url = {
16 | 'hostname': 'localhost',
17 | 'port': 3456
18 | }
19 |
20 | def switch_to_webview(driver):
21 | contexts = driver.contexts
22 | driver.context = contexts[-1]
23 | return driver
24 |
25 | def switch_to_native(driver):
26 | contexts = driver.contexts
27 | driver.context = contexts[0]
28 | return driver
29 |
30 | class MacacaTest(unittest.TestCase):
31 | @classmethod
32 | def setUpClass(cls):
33 | cls.driver = WebDriver(desired_caps, server_url)
34 | cls.initDriver()
35 |
36 | @classmethod
37 | def tearDownClass(cls):
38 | cls.driver.quit()
39 |
40 | @classmethod
41 | @retry
42 | def initDriver(cls):
43 | print("Retry connecting server...")
44 | cls.driver.init()
45 |
46 | def test_01_login(self):
47 | el = self.driver \
48 | .elements_by_class_name('android.widget.EditText')[0] \
49 | .send_keys('中文+Test+12345678') \
50 |
51 | el = self.driver \
52 | .elements_by_class_name('android.widget.EditText')[1] \
53 | .send_keys('111111')
54 |
55 | time.sleep(1)
56 | # self.driver.keys(Keys.ENTER.value + Keys.ESCAPE.value)
57 |
58 | self.driver \
59 | .element_by_name('Login') \
60 | .click()
61 |
62 | def test_02_scroll_tableview(self):
63 | self.driver \
64 | .wait_for_element_by_name('HOME') \
65 | .click()
66 |
67 | self.driver \
68 | .wait_for_element_by_name('list') \
69 | .click()
70 |
71 | def test_03_gesture(self):
72 |
73 | time.sleep(5)
74 |
75 | self.driver \
76 | .wait_for_element_by_name('Alert') \
77 | .click()
78 |
79 | time.sleep(5)
80 |
81 | self.driver \
82 | .accept_alert()
83 |
84 | time.sleep(3)
85 |
86 | self.driver \
87 | .back()
88 |
89 | time.sleep(3)
90 |
91 | self.driver \
92 | .wait_for_element_by_name('Gesture') \
93 | .click()
94 |
95 | time.sleep(3)
96 |
97 | self.driver \
98 | .touch('tap', {
99 | 'x': 100,
100 | 'y': 100
101 | })
102 |
103 | time.sleep(5)
104 |
105 | self.driver \
106 | .touch('doubleTap', {
107 | 'x': 100,
108 | 'y': 100
109 | })
110 |
111 | time.sleep(5)
112 |
113 | self.driver \
114 | .touch('press', {
115 | 'x': 100,
116 | 'y': 100,
117 | 'steps': 100
118 | })
119 |
120 | time.sleep(5)
121 |
122 | self.driver \
123 | .touch('drag', {
124 | 'fromX': 100,
125 | 'fromY': 100,
126 | 'toX': 100,
127 | 'toY': 600,
128 | 'steps': 100
129 | })
130 |
131 | time.sleep(5)
132 |
133 | self.driver.back()
134 |
135 | time.sleep(5)
136 |
137 | self.driver.back()
138 |
139 | def test_04_webview(self):
140 | self.driver \
141 | .wait_for_element_by_name('Webview') \
142 | .click()
143 |
144 | time.sleep(5)
145 | self.driver.save_screenshot('./webView.png') # save screen shot
146 |
147 | switch_to_webview(self.driver) \
148 | .wait_for_element_by_id('pushView') \
149 | .click()
150 |
151 | switch_to_webview(self.driver) \
152 | .wait_for_element_by_id('popView') \
153 | .click()
154 |
155 | def test_05_web(self):
156 | switch_to_native(self.driver) \
157 | .wait_for_element_by_name('Baidu') \
158 | .click()
159 |
160 | time.sleep(5)
161 | self.driver.save_screenshot("./baidu.png")
162 |
163 | switch_to_webview(self.driver) \
164 | .wait_for_element_by_id('index-kw') \
165 | .send_keys('macaca')
166 |
167 | self.driver \
168 | .wait_for_element_by_id('index-bn') \
169 | .click()
170 |
171 | def test_06_logout(self):
172 | switch_to_native(self.driver) \
173 | .wait_for_element_by_name('PERSONAL') \
174 | .click()
175 |
176 | self.driver.wait_for_element_by_name('Logout') \
177 | .click()
178 |
179 | if __name__ == '__main__':
180 | unittest.main()
181 |
--------------------------------------------------------------------------------