Mobile AGile
Godfrey Nolan
Agenda
- Android (am)
- iOS (pm)
ANDROID Agenda
- Why??
- Unit, UI and API testing 101
- Calculator Example
- More Tools - FIRST
- ETA Detroit
- jUnit Testing
- Espresso
- Postman / Newman
- Jenkins
iOs Agenda
- Why??
- Unit, UI and API testing 101
- Calculator Example
- No really why?? (FIRST)
- ETA Detroit
- XCTest
- XCUI
- Postman / Newman
- Jenkins
FOLLOW ALONG
git clone http://github.com/godfreynolan/CodeCraftsman
WHY
- Catch more mistakes
- Confidently make more changes
- Built in regression testing
- Extend the life of your codebase
Unit Testing intro
public double add(double firstOperand, double secondOperand) {
return firstOperand + secondOperand;
}
@Test
public void calculator_CorrectAdd_ReturnsTrue() {
assertEquals(7, add(3,4);
}
@Test
public void calculator_CorrectAdd_ReturnsTrue() {
assertEquals("Addition is broken", 7, add(3,4);
}
dependencies {
// Unit testing dependencies.
testCompile 'junit:junit:4.12'
}
UNIT TESTING 101
- Command line
- Setup and Teardown
- Assertions
- Parameters
- Code Coverage
C:\Users\godfrey\AndroidStudioProjects\BasicSample>gradlew test --continue
Downloading https://services.gradle.org/distributions/gradle-2.2.1-all.zip
................................................................................
..................................................
Unzipping C:\Users\godfrey\.gradle\wrapper\dists\gradle-2.2.1-all\6dibv5rcnnqlfbq9klf8imrndn\gradle-2.2.1-all.zip to C:\Users\godfrey\.gradle\wrapper\dists\gradle-2.2.1-all\6dibv5rcnnqlfbq9klf8imrndn
Download https://jcenter.bintray.com/com/google/guava/guava/17.0/guava-17.0.jar
Download https://jcenter.bintray.com/com/android/tools/lint/lint-api/24.2.3/lint-api-24.2.3.jar
Download https://jcenter.bintray.com/org/ow2/asm/asm-analysis/5.0.3/asm-analysis-5.0.3.jar
Download https://jcenter.bintray.com/com/android/tools/external/lombok/lombok-ast/0.2.3/lombok-ast-0.2.3.jar
:app:preBuild UP-TO-DATE
:app:preDebugBuild UP-TO-DATE
:app:checkDebugManifest
:app:prepareDebugDependencies
:app:compileDebugAidl
:app:compileDebugRenderscript
.
.
.
:app:compileReleaseUnitTestSources
:app:assembleReleaseUnitTest
:app:testRelease
:app:test
BUILD SUCCESSFUL
Total time: 3 mins 57.013 secs
public class CalculatorTest {
private Calculator mCalculator;
@Before
public void setUp() {
mCalculator = new Calculator();
}
@Test
public void calculator_CorrectAdd_ReturnsTrue() {
double resultAdd = mCalculator.add(3, 4);
assertEquals(7, resultAdd,0);
}
@After
public void tearDown() {
mCalculator = null;
}
}
UNIT TESTING 101
- assertEquals
- assertTrue
- assertFalse
- assertNull
- assertNotNull
- assertSame
- assertNotSame
- assertThat
- fail
@RunWith(Parameterized.class)
public class CalculatorParamTest {
private int mOperandOne, mOperandTwo, mExpectedResult;
private Calculator mCalculator;
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
{3, 4, 7}, {4, 3, 7}, {8, 2, 10}, {-1, 4, 3}, {3256, 4, 3260}
});
}
public CalculatorParamTest(int mOperandOne, int mOperandTwo, int mExpectedResult) {
this.mOperandOne = mOperandOne;
this.mOperandTwo = mOperandTwo;
this.mExpectedResult = mExpectedResult;
}
@Before
public void setUp() { mCalculator = new Calculator(); }
@Test
public void testAdd_TwoNumbers() {
int resultAdd = mCalculator.add(mOperandOne, mOperandTwo);
assertEquals(mExpectedResult, resultAdd, 0);
}
}
Espresso
- GUI Testing
- OnView
- OnData
- gradlew connectedCheck
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityTest {
@Rule
public ActivityTestRule<MainActivity> activityTestRule
= new ActivityTestRule<> (MainActivity.class);
@Test
public void helloWorldTest() {
onView(withId(R.id.hello_world))
.check(matches(withText(R.string.hello_world)));
}
}
@Test
public void helloWorldButtonTest(){
onView(withId(R.id.button))
.perform(click())
.check(matches(isEnabled()));
}
MORE TOOLS - BUT WHY??
- F(ast)
- I(solated)
- R(epeatable)
- S(elf-verifying)
- T(imely) i.e. TDD not TAD
MockiTO TEMPLATE
@Test
public void test() throws Exception {
// Arrange, prepare behavior
Helper aMock = mock(Helper.class);
when(aMock.isCalled()).thenReturn(true);
// Act
testee.doSomething(aMock);
// Assert - verify interactions
verify(aMock).isCalled();
}
when(methodIsCalled).thenReturn(aValue);
TROUBLE SHOOTING
- run gradlew build from the command line
- Add sdk.dir to local.properties
sdk.dir=/home/godfrey/android/sdk
TEST DRIVEN DEVELOPMENT (TDD)
- Unit testing vs TDD
- Why TDD
- Sample app
- Lessons learned
TEST DRIVEN DEVELOPMENT
- Write test first
- See it fail
- Write simplest possible solution
to get test to pass - Refactor
- Wash, Rinse, Repeat
TEST DRIVEN DEVELOPMENT
- Built in regression testing
- Longer life for your codebase
- YAGNI feature development
- Red/Green/Refactor helps
kill procrastination
TDD
You can't TDD w/o unit testing
TDD means writing the tests before the code
TDD is more painless than classic unit testing
Unit TESTING
You can unit test w/o TDD
Unit tests don't mandate when you write the tests
Unit tests are often written at the end of a coding cycle
STEPS
- Introduce Continuous Integration to build code
- Configure android projects for TDD
- Add minimal unit tests based on existing tests, add to CI
- Show team how to create unit tests
- Add testing code coverage metrics to CI, expect 5-10%
- Add Espresso tests
- Unit test new features or sprouts, mock existing objects
- Wrap or ring fence existing code, remove unused code
- Refactor wrapped code to get code coverage to 60-70%
(New refactoring in Android Studio)
CONTACT INFO
godfrey@riis.com
iOs Agenda
- Why??
- Unit, UI and API testing 101
- Calculator Example
- No really why?? (FIRST)
- ETA Detroit
- XCTest
- XCUI
- Postman / Newman
- Jenkins
WHY
- Catch more mistakes
- Confidently make more changes
- Built in regression testing
- Extend the life of your codebase
FOLLOW ALONG
git clone http://github.com/godfreynolan/CodeCraftsman
MORE TOOLS - BUT WHY??
- F(ast)
- I(solated)
- R(epeatable)
- S(elf-verifying)
- T(imely) i.e. TDD not TAD
Tools OF THE TRADE
-
XCTest
-
Cuckoo (Mocking)
-
XCUI
-
Postman
-
Jenkins
Cuckoo
-
Add Cuckoo to the test target in Podfile
-
Pod install
-
Add Run Script to build phases
-
Add GeneratedMocks.swift file to tests
# Define output file; change "${PROJECT_NAME}Tests" to your test's root source folder, if it's not the default name
OUTPUT_FILE="./${PROJECT_NAME}Tests/GeneratedMocks.swift"
echo "Generated Mocks File = ${OUTPUT_FILE}"
# Define input directory; change "${PROJECT_NAME}" to your project's root source folder, if it's not the default name
INPUT_DIR="./${PROJECT_NAME}"
echo "Mocks Input Directory = ${INPUT_DIR}"
# Generate mock files; include as many input files as you'd like to create mocks for
${PODS_ROOT}/Cuckoo/run generate --testable "${PROJECT_NAME}" \
--output "${OUTPUT_FILE}" \
"${INPUT_DIR}/JSONFetcher.swift"
# ... and so forth
# After running once, locate `GeneratedMocks.swift` and drag it into your Xcode test target group
XCUI
-
User Interface testing
-
Two options
▪Recorded tests
▪Roll your own
XCUI has 3 Components
-
XCUIApplication
-
Launch the app
-
-
XCUIElementQuery
-
Find the XCUI Element to test
-
-
XCUIElement
-
Perform Test
-
CONTACT INFO
godfrey@riis.com
Mobile Agile
By godfreynolan
Mobile Agile
- 734