Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Dart-side group()s #1634

Merged
merged 39 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
d503dd8
change `createDartTestGroup()` to work recursively
bartekpacia Aug 11, 2023
d4be6de
print all groups and tests (albeit twice)
bartekpacia Aug 11, 2023
9ed0fb5
deduplicate group and test names
bartekpacia Aug 11, 2023
2e60dc3
fix createDartTestGroup() tests
bartekpacia Aug 11, 2023
f5c09d9
implement deserializing DartTestGroup into a flat list of DartTestCases
bartekpacia Aug 14, 2023
d8e7484
use `listTestsFlat()` instead of `listFlatDartFiles()`, and remove th…
bartekpacia Aug 14, 2023
e491dc7
don't concat groups with a `dot` (this is a temporary change)
bartekpacia Aug 14, 2023
a3f7e20
fix typos in tests
bartekpacia Aug 14, 2023
43d3ec6
make it work
bartekpacia Aug 14, 2023
31592ea
example_test: enter current test name in a text field
bartekpacia Aug 14, 2023
c344e02
move permission-related tests under `integration_test/permissions`
bartekpacia Aug 14, 2023
8b2434b
clean up
bartekpacia Aug 15, 2023
af4fbd1
contracts.proto: merge DartTestGroup and DartTestCase into DartGroupE…
bartekpacia Aug 15, 2023
a4b3252
contracts.proto: regenerate
bartekpacia Aug 15, 2023
2cf225a
adapt Dart side to `DartGroupEntry`
bartekpacia Aug 15, 2023
be51202
adapt Android side to `DartGroupEntry`
bartekpacia Aug 15, 2023
4ea6ba6
clean ups
bartekpacia Aug 15, 2023
0ccfae2
disable xcbeautify because it slurps up xcodebuild exit code
bartekpacia Aug 15, 2023
34e3918
Merge branch 'master' into feature/dart_side_groups
bartekpacia Sep 11, 2023
535dfec
please `dart analyze`
bartekpacia Sep 11, 2023
d2d3eb5
bring back xcbeautify
bartekpacia Sep 11, 2023
43eb88f
DartGroupEntry: add `encodedFullName` field
bartekpacia Sep 11, 2023
1f2ab8a
Revert "DartGroupEntry: add `encodedFullName` field"
bartekpacia Sep 11, 2023
6185b2e
remove FIXME that is already fixed
bartekpacia Sep 12, 2023
85aa81f
iOS preparations: adjust `testCreateMethodNameFromPatrolGeneratedGroup`
bartekpacia Sep 12, 2023
c9c68b2
`group()`s work both on Android and iOS
bartekpacia Sep 12, 2023
84c6bfd
Patrol_DartGroupEntry.listTestsFlat() extensions: clean up
bartekpacia Sep 12, 2023
083cf70
contracts.proto: remove fullName from DartGroupEntry
bartekpacia Sep 12, 2023
a20e1f3
clean up: RunnerUITests - bring back macro usage
bartekpacia Sep 12, 2023
1b44a73
update comments and outdated variable names
bartekpacia Sep 12, 2023
a53e42a
improve code comment
bartekpacia Sep 12, 2023
35823b3
fix test names on iOS
bartekpacia Sep 12, 2023
0345cf4
patrol-prepare workflow: move set -o pipefail to a separate line
bartekpacia Sep 12, 2023
a2db518
remove leftover comment
bartekpacia Sep 12, 2023
04b41fb
example app tests: handle `else` case for Platform
bartekpacia Sep 12, 2023
86b9b12
DartGroupEntry.listDartTests: fail more loudly when invariant is viol…
bartekpacia Sep 12, 2023
d0665c2
convert unnecessary `late`s to `final`s
bartekpacia Sep 13, 2023
19fecdc
TestBundler: update `print` message in generated test_bundle.dart
bartekpacia Sep 13, 2023
ef29f1d
bring back old example_test
bartekpacia Sep 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/patrol-prepare.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,13 @@ jobs:
- name: Run unit tests
working-directory: packages/patrol/example/ios
run: |
xcodebuild test \
set -o pipefail && xcodebuild test \
bartekpacia marked this conversation as resolved.
Show resolved Hide resolved
-workspace Runner.xcworkspace \
-scheme Runner \
-only-testing RunnerTests \
-configuration Debug \
-sdk iphoneos -destination 'platform=iOS Simulator,name=iPhone 14' \
-derivedDataPath ../build/ios_unit | xcbeautify
-derivedDataPath ../build/ios_unit | xcbeautify --renderer github-actions

prepare-flutter:
name: Flutter ${{ matrix.flutter-version }}
Expand Down
15 changes: 8 additions & 7 deletions contracts.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ service PatrolAppService {
}

message ListDartTestsResponse {
DartTestGroup group = 1;
DartGroupEntry group = 1;
}

message DartTestGroup {
message DartGroupEntry {
string name = 1;
repeated DartTestCase tests = 2;
repeated DartTestGroup groups = 3;
}
GroupEntryType type = 3;
repeated DartGroupEntry entries = 4;

message DartTestCase {
string name = 1;
enum GroupEntryType {
GROUP = 0;
TEST = 1;
}
}

message RunDartTestRequest {
Expand Down
2 changes: 1 addition & 1 deletion dev/cli_tests/patrol_develop_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ void main(List<String> args) async {
[
'develop',
...['--target', 'integration_test/example_test.dart'],
...args
...args,
],
runInShell: true,
workingDirectory: exampleAppDirectory.path,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package pl.leancode.patrol
import androidx.test.uiautomator.By
import androidx.test.uiautomator.BySelector
import androidx.test.uiautomator.UiSelector
import pl.leancode.patrol.contracts.Contracts
import pl.leancode.patrol.contracts.Contracts.DartTestGroup
import pl.leancode.patrol.contracts.Contracts.DartGroupEntry
import pl.leancode.patrol.contracts.Contracts.Selector
import pl.leancode.patrol.contracts.copy

private fun Contracts.Selector.isEmpty(): Boolean {
private fun Selector.isEmpty(): Boolean {
return (
!hasText() &&
!hasTextStartsWith() &&
Expand All @@ -23,7 +24,7 @@ private fun Contracts.Selector.isEmpty(): Boolean {
)
}

fun Contracts.Selector.toUiSelector(): UiSelector {
fun Selector.toUiSelector(): UiSelector {
var selector = UiSelector()

if (hasText()) {
Expand Down Expand Up @@ -77,7 +78,7 @@ fun Contracts.Selector.toUiSelector(): UiSelector {
return selector
}

fun Contracts.Selector.toBySelector(): BySelector {
fun Selector.toBySelector(): BySelector {
if (isEmpty()) {
throw PatrolException("Selector is empty")
}
Expand Down Expand Up @@ -184,21 +185,28 @@ fun Contracts.Selector.toBySelector(): BySelector {
return bySelector
}

fun DartTestGroup.listFlatDartFiles(): List<String> {
val files = mutableListOf<String>()
for (group in groupsList) {
files.addAll(group.listGroups())
}

return files
}

// Recursively lists groups in this group.
private fun DartTestGroup.listGroups(): List<String> {
val groups = mutableListOf<String>(this.name)
for (group in groupsList) {
groups.addAll(group.listGroups())
}

return groups
/**
* Flattens the structure of a DartTestSuite into a flat list of tests.
*/
fun DartGroupEntry.listTestsFlat(parentGroupName: String = ""): List<DartGroupEntry> {
val tests = mutableListOf<DartGroupEntry>()

for (test in entriesList) {
if (test.type == DartGroupEntry.GroupEntryType.TEST) {
bartekpacia marked this conversation as resolved.
Show resolved Hide resolved
if (parentGroupName.isEmpty()) {
// This case is invalid, because every test will have at least 1 named group - its filename.
throw IllegalStateException("Test $test has no named parent group")
}

tests.add(test.copy { name = "$parentGroupName ${test.name}" })
} else if (test.type == DartGroupEntry.GroupEntryType.GROUP) {
if (parentGroupName.isEmpty()) {
tests.addAll(test.listTestsFlat(parentGroupName = test.name))
} else {
tests.addAll(test.listTestsFlat(parentGroupName = "$parentGroupName ${test.name}"))
}
}
}

return tests
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public PatrolAppServiceClient(String target) {
blockingStub = PatrolAppServiceGrpc.newBlockingStub(channel);
}

public DartTestGroup listDartTests() throws StatusRuntimeException {
public DartGroupEntry listDartTests() throws StatusRuntimeException {
Empty request = Empty.newBuilder().build();
ListDartTestsResponse response = blockingStub.listDartTests(request);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnitRunner;
import io.grpc.StatusRuntimeException;
import pl.leancode.patrol.contracts.Contracts.DartTestGroup;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;

import static pl.leancode.patrol.contracts.Contracts.DartGroupEntry;
import static pl.leancode.patrol.contracts.Contracts.RunDartTestResponse;

/**
Expand Down Expand Up @@ -53,7 +55,8 @@ public void onCreate(Bundle arguments) {
* This default behavior doesn't work with Flutter apps. That's because in Flutter
* apps, the tests are in the app itself, so running only the instrumentation
* during the initial run is not enough.
* The app must also be run, and queried for Dart tests That's what this method does.
* The app must also be run, and queried for Dart tests.
* That's what this method does.
* </p>
*/
public void setUp(Class<?> activityClass) {
Expand Down Expand Up @@ -106,10 +109,15 @@ public Object[] listDartTests() {
final String TAG = "PatrolJUnitRunner.listDartTests(): ";

try {
final DartTestGroup dartTestGroup = patrolAppServiceClient.listDartTests();
Object[] dartTestFiles = ContractsExtensionsKt.listFlatDartFiles(dartTestGroup).toArray();
Logger.INSTANCE.i(TAG + "Got Dart tests: " + Arrays.toString(dartTestFiles));
return dartTestFiles;
final DartGroupEntry dartTestGroup = patrolAppServiceClient.listDartTests();
List<DartGroupEntry> dartTestCases = ContractsExtensionsKt.listTestsFlat(dartTestGroup, "");
List<String> dartTestCaseNamesList = new ArrayList<>();
for (DartGroupEntry dartTestCase : dartTestCases) {
dartTestCaseNamesList.add(dartTestCase.getName());
}
Object[] dartTestCaseNames = dartTestCaseNamesList.toArray();
Logger.INSTANCE.i(TAG + "Got Dart tests: " + Arrays.toString(dartTestCaseNames));
return dartTestCaseNames;
} catch (StatusRuntimeException e) {
Logger.INSTANCE.e(TAG + "Failed to list Dart tests: ", e);
throw e;
Expand Down
Loading
Loading