Mobile unit testing
Skill almasumdev/awesome-mobile-testing-agent-skills/.github/skills/unit/mobile-unit-testing
Expert guidance on writing fast, deterministic unit tests for mobile codebases across Kotlin, Swift, Dart, and TypeScript. Use when asked to structure unit tests, pick a runner, or apply the AAA pattern.From its SKILL.md
npx -y skills add almasumdev/awesome-mobile-testing-agent-skills --skill mobile-unit-testingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
4.3 KB, ~1.0k tokens by cl100k_base, as published. Nobody here has run it
Mobile Unit Testing
Instructions
Unit tests are the foundation of the mobile test pyramid. They must be hermetic (no network, no filesystem outside temp dirs, no device dependency), deterministic, and fast (< 10 ms each as a rule of thumb). Every other test layer exists to cover gaps unit tests cannot reach — not to compensate for missing unit tests.
1. Scope of a Unit Test
A unit test covers one public behavior of one class or function. It should:
- Run on the host JVM / host Swift / Node / Dart VM — never on an emulator or device.
- Not touch
Context,Application,UIApplication,Activity,WidgetsBinding, or any platform singleton. If it does, it is an integration or instrumentation test. - Assert on return values or observable state, not on how the code reached that state.
2. Structure: Arrange / Act / Assert
Keep the three phases visually separated. One logical assertion per test; multiple expect lines that assert on the same logical outcome are fine.
Kotlin (JUnit5 + Kotest assertions):
@Test
fun `checkout applies 10 percent loyalty discount`() {
// Arrange
val cart = Cart(items = listOf(item(price = 100)))
val sut = CheckoutCalculator(discount = LoyaltyDiscount(tierPercent = 10))
// Act
val total = sut.total(cart)
// Assert
total shouldBe Money.usd(90)
}
Swift (XCTest):
func test_checkout_appliesTenPercentLoyaltyDiscount() {
let cart = Cart(items: [.item(price: 100)])
let sut = CheckoutCalculator(discount: LoyaltyDiscount(tierPercent: 10))
let total = sut.total(for: cart)
XCTAssertEqual(total, .usd(90))
}
Dart (package:test):
test('checkout applies 10% loyalty discount', () {
final cart = Cart(items: [Item(price: 100)]);
final sut = CheckoutCalculator(discount: LoyaltyDiscount(tierPercent: 10));
expect(sut.total(cart), Money.usd(90));
});
TypeScript (Jest):
test('checkout applies 10% loyalty discount', () => {
const cart = new Cart([{ price: 100 }]);
const sut = new CheckoutCalculator(new LoyaltyDiscount(10));
expect(sut.total(cart)).toEqual(Money.usd(90));
});
3. Naming
Tests are read ten times for every time they are written. Prefer behavioral names:
methodName_condition_expectedResult(Java tradition)`applies 10 percent loyalty discount when tier is gold`(Kotlin/Swift/Dart)when X then Ysentences (BDD style)
Avoid testFoo1, testFoo2 — the next reader cannot tell them apart on a failure dashboard.
4. Test Doubles
Prefer fakes over mocks when the collaborator has meaningful state (e.g., a repository, a clock, a feature-flag store). Use mocks only to verify interactions that are the behavior (e.g., "the analytics event was emitted once"). See the mocking-strategies skill for library choices.
5. Parameterized Tests
When the same behavior has many input rows, parameterize instead of copy-pasting:
- Kotlin: JUnit5
@ParameterizedTest+@MethodSource, or KotestforAll. - Swift: XCTest has no native parameterization; use
forover a table inside oneXCTContext.runActivity. - Dart: wrap
testcalls in a loop over a table of cases. - TS/Jest:
test.each([...]).
6. What NOT to unit-test
- Framework glue (Activity lifecycle, UIViewController presentation, Navigator stacks) — belongs in UI or integration tests.
- Third-party libraries — trust the library; test your wrapper instead.
- Trivial getters/setters /
data classequality — test the behavior that depends on them.
7. Checklist
- Test runs on host (JVM / Node / Dart VM / host Swift), not on device/emulator.
- No real clock, RNG, network, filesystem, or platform channels.
- Arrange / Act / Assert visible at a glance; one logical assertion.
- Name describes behavior, not the method under test alone.
- Parameterized when there are > 3 near-identical cases.
- Failure message points to the defect, not to line numbers in the test.
- Test passes alone and inside the full suite (no ordering dependency).
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.