├── .github
└── PULL_REQUEST_TEMPLATE.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── NOTICE
├── README.md
├── packageTest.sh
├── pom.xml
├── readme_images
└── appium-tests.gif
├── src
├── main
│ └── assembly
│ │ └── zip.xml
└── test
│ ├── java
│ ├── Pages
│ │ ├── BasePage.java
│ │ ├── LoginPage.java
│ │ ├── NavigationPage.java
│ │ └── WaitConfig.java
│ └── Tests
│ │ ├── AbstractBaseTests
│ │ └── TestBase.java
│ │ └── LoginTest.java
│ └── resources
│ └── LoginTest
│ └── LoginTest.feature
└── start-appium-android.sh
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | *Issue #, if available:*
2 |
3 | *Description of changes:*
4 |
5 |
6 | By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
7 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Code of Conduct
2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
4 | opensource-codeofconduct@amazon.com with any additional questions or comments.
5 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
4 | documentation, we greatly value feedback and contributions from our community.
5 |
6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
7 | information to effectively respond to your bug report or contribution.
8 |
9 |
10 | ## Reporting Bugs/Feature Requests
11 |
12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features.
13 |
14 | When filing an issue, please check [existing open](https://github.com/aws-samples/aws-device-farm-appium-cucumber-tests-for-sample-app/issues), or [recently closed](https://github.com/aws-samples/aws-device-farm-appium-cucumber-tests-for-sample-app/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already
15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
16 |
17 | * A reproducible test case or series of steps
18 | * The version of our code being used
19 | * Any modifications you've made relevant to the bug
20 | * Anything unusual about your environment or deployment
21 |
22 |
23 | ## Contributing via Pull Requests
24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
25 |
26 | 1. You are working against the latest source on the *master* branch.
27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
29 |
30 | To send us a pull request, please:
31 |
32 | 1. Fork the repository.
33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
34 | 3. Ensure local tests pass.
35 | 4. Commit to your fork using clear commit messages.
36 | 5. Send us a pull request, answering any default questions in the pull request interface.
37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
38 |
39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
41 |
42 |
43 | ## Finding contributions to work on
44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws-samples/aws-device-farm-appium-cucumber-tests-for-sample-app/labels/help%20wanted) issues is a great place to start.
45 |
46 |
47 | ## Code of Conduct
48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
50 | opensource-codeofconduct@amazon.com with any additional questions or comments.
51 |
52 |
53 | ## Security issue notifications
54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
55 |
56 |
57 | ## Licensing
58 |
59 | See the [LICENSE](https://github.com/aws-samples/aws-device-farm-appium-cucumber-tests-for-sample-app/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
60 |
61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes.
62 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | AWS Device Farm Appium Cucumber Tests For Sample App
2 | Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## AWS Device Farm Appium Cucumber Tests For Sample App
2 |
3 | Sample Appium Cucumber tests for Android sample app that can be used on AWS Device Farm.
4 |
5 | Instructions to package and run this test can be found [here.](https://aws.amazon.com/blogs/mobile/testing-mobile-apps-with-cucumber-and-appium-through-testng-on-aws-device-farm/)
6 |
7 | ## License
8 |
9 | This library is licensed under the Apache 2.0 License.
10 |
--------------------------------------------------------------------------------
/packageTest.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | mvn clean package -DskipTests=true
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.amazon.aws.adf.referenceapp.appium.test
8 | Referenceapp-Appium-Test
9 | 1.0-SNAPSHOT
10 | jar
11 | ReferenceAppAppiumTests
12 | http://maven.apache.org
13 |
14 |
15 |
16 | org.testng
17 | testng
18 | 6.8.8
19 | test
20 |
21 |
22 | io.appium
23 | java-client
24 | 3.1.0
25 |
26 |
27 | info.cukes
28 | cucumber-java
29 | 1.2.5
30 | test
31 |
32 |
33 | info.cukes
34 | cucumber-testng
35 | 1.2.4
36 |
37 |
38 |
39 |
40 |
41 |
42 | org.apache.maven.plugins
43 | maven-jar-plugin
44 | 2.6
45 |
46 |
47 |
48 | test-jar
49 |
50 |
51 |
52 |
53 |
54 | org.apache.maven.plugins
55 | maven-dependency-plugin
56 | 2.10
57 |
58 |
59 | copy-dependencies
60 | package
61 |
62 | copy-dependencies
63 |
64 |
65 | ${project.build.directory}/dependency-jars/
66 |
67 |
68 |
69 |
70 |
71 | maven-assembly-plugin
72 | 2.5.4
73 |
74 |
75 | package
76 |
77 | single
78 |
79 |
80 | zip-with-dependencies
81 | false
82 |
83 | src/main/assembly/zip.xml
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/readme_images/appium-tests.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/aws-device-farm-appium-cucumber-tests-for-sample-app/ce71432fbfc53eedf13ebf27699aa5c8565066a0/readme_images/appium-tests.gif
--------------------------------------------------------------------------------
/src/main/assembly/zip.xml:
--------------------------------------------------------------------------------
1 |
15 |
20 | zip
21 |
22 | zip
23 |
24 | false
25 |
26 |
27 | ${project.build.directory}
28 | ./
29 |
30 | *.jar
31 |
32 |
33 |
34 | ${project.build.directory}
35 | ./
36 |
37 | /dependency-jars/
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/test/java/Pages/BasePage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License").
5 | * You may not use this file except in compliance with the License.
6 | * A copy of the License is located at
7 | *
8 | * http://aws.amazon.com/apache2.0
9 | *
10 | * or in the "license" file accompanying this file. This file is distributed
11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 | * express or implied. See the License for the specific language governing
13 | * permissions and limitations under the License.
14 | */
15 |
16 | package Pages;
17 |
18 |
19 | import io.appium.java_client.AppiumDriver;
20 | import io.appium.java_client.pagefactory.AppiumFieldDecorator;
21 | import org.openqa.selenium.WebElement;
22 | import org.openqa.selenium.support.PageFactory;
23 |
24 | import java.util.concurrent.TimeUnit;
25 |
26 | /**
27 | * A base for all the pages within the suite
28 | */
29 | public abstract class BasePage {
30 | private static final int KEYBOARD_ANIMATION_DELAY = 1000;
31 | private static final int XML_REFRESH_DELAY = 1000;
32 |
33 | /**
34 | * The driver
35 | */
36 | protected final AppiumDriver driver;
37 |
38 | /**
39 | * A base constructor that sets the page's driver
40 | *
41 | * The page structure is being used within this test in order to separate the
42 | * page actions from the tests.
43 | *
44 | * Please use the AppiumFieldDecorator class within the page factory. This way annotations
45 | * like @AndroidFindBy within the page objects.
46 | *
47 | * @param driver the appium driver created in the beforesuite method.
48 | */
49 | protected BasePage(AppiumDriver driver){
50 | this.driver = driver;
51 | PageFactory.initElements(new AppiumFieldDecorator(driver, 5, TimeUnit.SECONDS), this);
52 | }
53 |
54 | /**
55 | * Tries three times to send text to element properly.
56 | *
57 | * Note: This method was needed because Appium sometimes sends text to textboxes incorrectly.
58 | *
59 | * @param input String to be sent
60 | * @param element WebElement to receive text, cannot be a secure text field.
61 | * @param appendNewLine true to append a new line character to incoming string when sending to element, else false
62 | *
63 | * @return true if keys were successfully sent, otherwise false.
64 | */
65 | protected boolean sendKeysToElement(String input, WebElement element, boolean appendNewLine) throws InterruptedException {
66 | final int MAX_ATTEMPTS = 3;
67 | int attempts = 0;
68 |
69 | do {
70 | element.clear();
71 | Thread.sleep(KEYBOARD_ANIMATION_DELAY);
72 |
73 | if (appendNewLine) {
74 | element.sendKeys(input + "\n");
75 | } else {
76 | element.sendKeys(input);
77 | }
78 |
79 | Thread.sleep(XML_REFRESH_DELAY);
80 | } while (!element.getText().contains(input) && ++attempts < MAX_ATTEMPTS);
81 |
82 | return element.getText().contains(input);
83 | }
84 | }
--------------------------------------------------------------------------------
/src/test/java/Pages/LoginPage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License").
5 | * You may not use this file except in compliance with the License.
6 | * A copy of the License is located at
7 | *
8 | * http://aws.amazon.com/apache2.0
9 | *
10 | * or in the "license" file accompanying this file. This file is distributed
11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 | * express or implied. See the License for the specific language governing
13 | * permissions and limitations under the License.
14 | */
15 |
16 | package Pages;
17 |
18 | import io.appium.java_client.AppiumDriver;
19 | import io.appium.java_client.MobileElement;
20 | import io.appium.java_client.pagefactory.AndroidFindBy;
21 |
22 | /**
23 | * A login page
24 | */
25 | public class LoginPage extends BasePage {
26 | private static final int KEYBOARD_ANIMATION_DELAY = 1000;
27 |
28 | /**
29 | * The login button
30 | */
31 | @AndroidFindBy(id = "com.amazonaws.devicefarm.android.referenceapp:id/login_button")
32 | private MobileElement loginButton;
33 |
34 | /**
35 | * The user name input
36 | */
37 | @AndroidFindBy(id = "com.amazonaws.devicefarm.android.referenceapp:id/username_text_input")
38 | private MobileElement usernameField;
39 |
40 | /**
41 | * The password input
42 | */
43 | @AndroidFindBy(id = "com.amazonaws.devicefarm.android.referenceapp:id/password_text_input")
44 | private MobileElement passwordField;
45 |
46 | public LoginPage(AppiumDriver driver) {
47 | super(driver);
48 | }
49 |
50 | /**
51 | * Tries to login with a set of credentials
52 | *
53 | * @param username the username
54 | * @param password the password
55 | *
56 | * @return true if username was entered in correctly, else false.
57 | */
58 | public boolean login(String username, String password) throws InterruptedException {
59 | boolean usernameStatus = sendKeysToElement(username, usernameField, false);
60 |
61 | passwordField.click();
62 | Thread.sleep(KEYBOARD_ANIMATION_DELAY);
63 | passwordField.sendKeys(password);
64 |
65 | loginButton.click();
66 |
67 | return usernameStatus;
68 | }
69 |
70 | /**
71 | *
72 | * @return the login message
73 | */
74 | public String getMessage() {
75 | return driver.findElementById("Alt Message").getText();
76 | }
77 |
78 | /**
79 | * Checks to see if back at login page
80 | *
81 | * @return is back at login
82 | */
83 | public boolean checkIfBackAtLogin() {
84 | return loginButton.isDisplayed() && usernameField.isDisplayed() && passwordField.isDisplayed();
85 | }
86 |
87 | /**
88 | * Presses the logout/try again button
89 | */
90 | public void pressAltButton() {
91 | driver.findElementById("Alt Button").click();
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/test/java/Pages/NavigationPage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License").
5 | * You may not use this file except in compliance with the License.
6 | * A copy of the License is located at
7 | *
8 | * http://aws.amazon.com/apache2.0
9 | *
10 | * or in the "license" file accompanying this file. This file is distributed
11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 | * express or implied. See the License for the specific language governing
13 | * permissions and limitations under the License.
14 | */
15 |
16 | package Pages;
17 |
18 | import io.appium.java_client.AppiumDriver;
19 | import io.appium.java_client.pagefactory.AndroidFindBy;
20 | import org.openqa.selenium.NoSuchElementException;
21 | import org.openqa.selenium.WebElement;
22 |
23 | import java.util.ArrayList;
24 | import java.util.List;
25 |
26 | /**
27 | * A page for navigation drawer
28 | */
29 | public class NavigationPage extends BasePage{
30 |
31 | private final int TRIES = 5;
32 |
33 | /**
34 | * Get the toggle button
35 | */
36 | @AndroidFindBy(accessibility = "ReferenceApp")
37 | private WebElement toggle;
38 |
39 | public NavigationPage(AppiumDriver driver) {
40 | super(driver);
41 | }
42 |
43 | /**
44 | * Go to a specific category within the navigation drawer
45 | *
46 | * @param categoryName category
47 | */
48 | public void gotoCategory(String categoryName) {
49 | int counter = 0;
50 | toggle.click();
51 | try {
52 | Thread.sleep(WaitConfig.DRAWER_ANIMATION_WAIT);
53 | } catch (InterruptedException e) {
54 | e.printStackTrace();
55 | }
56 |
57 | WebElement categoryElement = null;
58 | List categoryElements;
59 |
60 | while (categoryElement == null) {
61 | counter++;
62 | if (counter == TRIES)
63 | return;
64 | categoryElements = driver.findElementsById("com.amazonaws.devicefarm.android.referenceapp:id/drawer_row_title");
65 | for (WebElement categoryTitleElement: categoryElements){
66 | String titleText = categoryTitleElement.getText();
67 | if (titleText.equalsIgnoreCase(categoryName)) categoryElement = categoryTitleElement;
68 |
69 | }
70 | if (categoryElement == null) {
71 | driver.scrollTo(categoryName);
72 | }
73 | }
74 |
75 | categoryElement.click();
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/test/java/Pages/WaitConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License").
5 | * You may not use this file except in compliance with the License.
6 | * A copy of the License is located at
7 | *
8 | * http://aws.amazon.com/apache2.0
9 | *
10 | * or in the "license" file accompanying this file. This file is distributed
11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 | * express or implied. See the License for the specific language governing
13 | * permissions and limitations under the License.
14 | */
15 |
16 | package Pages;
17 |
18 | public class WaitConfig {
19 | public static final int DRAWER_ANIMATION_WAIT = 2000;
20 | public static final int VIEWPAGE_BEFORE_WAIT = 1000;
21 | public static final int VIEWPAGE_BEFORE_AFTER = 4000;
22 | }
--------------------------------------------------------------------------------
/src/test/java/Tests/AbstractBaseTests/TestBase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License").
5 | * You may not use this file except in compliance with the License.
6 | * A copy of the License is located at
7 | *
8 | * http://aws.amazon.com/apache2.0
9 | *
10 | * or in the "license" file accompanying this file. This file is distributed
11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 | * express or implied. See the License for the specific language governing
13 | * permissions and limitations under the License.
14 | */
15 |
16 | package Tests.AbstractBaseTests;
17 |
18 | import cucumber.api.testng.AbstractTestNGCucumberTests;
19 |
20 | import Pages.NavigationPage;
21 | import io.appium.java_client.MobileElement;
22 | import io.appium.java_client.android.AndroidDriver;
23 | import org.openqa.selenium.remote.DesiredCapabilities;
24 | import org.testng.annotations.*;
25 |
26 | import java.net.MalformedURLException;
27 | import java.net.URL;
28 | import java.util.concurrent.TimeUnit;
29 |
30 | /**
31 | * An abstract base for all of the Android tests within this package
32 | *
33 | * Responsible for setting up the Appium test Driver
34 | */
35 | public abstract class TestBase extends AbstractTestNGCucumberTests {
36 | /**
37 | * Make the driver static. This allows it to be created only once
38 | * and used across all of the test classes.
39 | */
40 | public static AndroidDriver driver;
41 |
42 | /**
43 | * This allows the navigation to work within the app.
44 | * The category name is returned so we can navigate to it from the navigation
45 | * drawer.
46 | *
47 | * @return The name of the Android category
48 | */
49 | public abstract String getName();
50 |
51 | /**
52 | * A page containing the navigation drawer
53 | */
54 | private NavigationPage navigationPage;
55 |
56 | /**
57 | * Method to initialize the test's page
58 | */
59 | @BeforeTest
60 | public abstract void setUpPage();
61 |
62 | /**
63 | * This method runs before any other method.
64 | *
65 | * Appium follows a client - server model:
66 | * We are setting up our appium client in order to connect to Device Farm's appium server.
67 | *
68 | * We do not need to and SHOULD NOT set our own DesiredCapabilities
69 | * Device Farm creates custom settings at the server level. Setting your own DesiredCapabilities
70 | * will result in unexpected results and failures.
71 | *
72 | * @throws MalformedURLException An exception that occurs when the URL is wrong
73 | */
74 | @BeforeSuite
75 | public void setUpAppium() throws MalformedURLException {
76 |
77 | final String URL_STRING = "http://127.0.0.1:4723/wd/hub";
78 |
79 | URL url = new URL(URL_STRING);
80 |
81 | //Use a empty DesiredCapabilities object
82 | DesiredCapabilities capabilities = new DesiredCapabilities();
83 |
84 | //Set the DesiredCapabilities capabilities only for local development
85 | capabilities.setCapability("platformName", "Android");
86 | capabilities.setCapability("deviceName", "Android Emulator");
87 | capabilities.setCapability("appPackage", "com.amazonaws.devicefarm.android.referenceapp");
88 | capabilities.setCapability("appActivity", "com.amazonaws.devicefarm.android.referenceapp.Activities.MainActivity");
89 | capabilities.setCapability("udid", "emulator-5554");
90 |
91 | driver = new AndroidDriver(url, capabilities);
92 |
93 | //Use a higher value if your mobile elements take time to show up
94 | driver.manage().timeouts().implicitlyWait(35, TimeUnit.SECONDS);
95 | }
96 |
97 | /**
98 | * Always remember to quit
99 | */
100 | @AfterSuite
101 | public void tearDownAppium() {
102 | driver.quit();
103 | }
104 |
105 | /**
106 | *
107 | * Creates a navigation page and navigates to the Class' category
108 | * within the navigation drawer
109 | *
110 | */
111 | @BeforeClass
112 | public void navigateTo() throws InterruptedException {
113 | navigationPage = new NavigationPage(driver);
114 | navigationPage.gotoCategory(getName());
115 | }
116 |
117 | /**
118 | * Restart the app after every test class to go back to the main
119 | * screen and to reset the behavior
120 | */
121 | @AfterClass
122 | public void restartApp() {
123 | driver.resetApp();
124 | }
125 | }
--------------------------------------------------------------------------------
/src/test/java/Tests/LoginTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License").
5 | * You may not use this file except in compliance with the License.
6 | * A copy of the License is located at
7 | *
8 | * http://aws.amazon.com/apache2.0
9 | *
10 | * or in the "license" file accompanying this file. This file is distributed
11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 | * express or implied. See the License for the specific language governing
13 | * permissions and limitations under the License.
14 | */
15 |
16 | package Tests;
17 |
18 | import cucumber.api.CucumberOptions;
19 | import cucumber.api.java.en.Given;
20 | import cucumber.api.java.en.Then;
21 | import cucumber.api.java.en.When;
22 |
23 |
24 | import Pages.LoginPage;
25 | import Tests.AbstractBaseTests.TestBase;
26 | import org.testng.Assert;
27 | import org.testng.annotations.AfterMethod;
28 | import org.testng.annotations.BeforeTest;
29 | import org.testng.annotations.Test;
30 |
31 | /**
32 | * Tests for a login page
33 | */
34 |
35 |
36 | @CucumberOptions(
37 | strict = true,
38 | monochrome = true,
39 | features = "classpath:LoginTest",
40 | plugin = {"pretty"}
41 | )
42 | public class LoginTest extends TestBase {
43 | private static final String LOGIN_SUCCESS_MESSAGE = "You are logged on as admin";
44 | private static final String LOGIN_FAIL_MESSAGE = "You gave me the wrong username and password";
45 | private static final String CORRECT_USER_NAME = "admin";
46 | private static final String CORRECT_PASSWORD = "password";
47 | private static final String FAIL_USER_NAME = "Wrong User";
48 | private static final String FAIL_PASSWORD = "12345";
49 | private static final String BAD_TEXT_ENTRY_MSG = "Username sent to text field incorrectly";
50 |
51 | private LoginPage loginPage;
52 |
53 | @Override
54 | public String getName() {
55 | return "Login Page";
56 | }
57 |
58 | /**
59 | * Creates a login
60 | */
61 | @Given("^I navigate to the login page$")
62 | public void setUpPage() {
63 | loginPage = new LoginPage(driver);
64 | }
65 |
66 | /**
67 | * Tests logging in with valid credentials by verifying if the login message is correct
68 | */
69 | @Given("^username is correct$")
70 | public void loginSuccess() throws InterruptedException {
71 | Assert.assertTrue(loginPage.login(CORRECT_USER_NAME, CORRECT_PASSWORD));
72 | Assert.assertEquals(loginPage.getMessage(), LOGIN_SUCCESS_MESSAGE);
73 | }
74 |
75 | /**
76 | * Tests logging in with invalid credentials by verifying if the error message is correct
77 | */
78 | @Given("^username is bad$")
79 | public void loginFail() throws InterruptedException {
80 | Assert.assertTrue(loginPage.login(FAIL_USER_NAME, FAIL_PASSWORD));
81 | Assert.assertEquals(loginPage.getMessage(), LOGIN_FAIL_MESSAGE);
82 | }
83 |
84 | /**
85 | * After each test method, logout or try again
86 | */
87 | @Then("^log out$")
88 | public void logOut() {
89 | loginPage.pressAltButton();
90 | Assert.assertTrue(loginPage.checkIfBackAtLogin());
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/test/resources/LoginTest/LoginTest.feature:
--------------------------------------------------------------------------------
1 | Feature: Does the login page work?
2 | We want the login page to work when the login credentials are valid, and fail otherwise
3 |
4 | Background: A Login Page
5 | Given I navigate to the login page
6 |
7 | Scenario: Login fails
8 | Given username is bad
9 | Then log out
10 |
11 |
12 | Scenario: Login succeeds
13 | Given username is correct
14 | Then log out
--------------------------------------------------------------------------------
/start-appium-android.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | function die {
4 | echo $1
5 | exit 1
6 | }
7 |
8 | pkg_root_dir=`find $PWD | grep "/Config$" | head -n 1 | xargs dirname`
9 | app_filename="$pkg_root_dir/app/app.apk"
10 | ls -1 $app_filename || die "Did not find app in $pkg_root_dir"
11 |
12 | appium --pre-launch --app-pkg com.amazonaws.devicefarm.android.referenceapp --app-activity .Activities.MainActivity --platform-name Android --app $app_filename
13 |
--------------------------------------------------------------------------------