|
@@ -5,15 +5,21 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
|
import androidx.test.filters.LargeTest
|
|
import androidx.test.filters.LargeTest
|
|
|
import androidx.test.platform.app.InstrumentationRegistry
|
|
import androidx.test.platform.app.InstrumentationRegistry
|
|
|
import androidx.test.uiautomator.By
|
|
import androidx.test.uiautomator.By
|
|
|
-import androidx.test.uiautomator.Direction
|
|
|
|
|
import androidx.test.uiautomator.Until
|
|
import androidx.test.uiautomator.Until
|
|
|
import org.junit.Rule
|
|
import org.junit.Rule
|
|
|
import org.junit.Test
|
|
import org.junit.Test
|
|
|
import org.junit.runner.RunWith
|
|
import org.junit.runner.RunWith
|
|
|
|
|
+import java.util.regex.Pattern
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * This test class generates a basic startup baseline profile for the target package.
|
|
|
|
|
- **/
|
|
|
|
|
|
|
+ * 生成 baseline profile。
|
|
|
|
|
+ *
|
|
|
|
|
+ * 关键:journey 必须真正打开一本书进入阅读器,否则开书热路径(Compose 组合、
|
|
|
|
|
+ * ChapterProvider/TextChapterLayout 排版、ReadView 绘制)不会被采样进 profile,
|
|
|
|
|
+ * release 首次开书只能主线程内联 JIT,产生明显加载卡顿。
|
|
|
|
|
+ *
|
|
|
|
|
+ * 运行前提:目标设备书架里至少有一本书(本仓库用连接的真机生成,见 useConnectedDevices)。
|
|
|
|
|
+ */
|
|
|
@RunWith(AndroidJUnit4::class)
|
|
@RunWith(AndroidJUnit4::class)
|
|
|
@LargeTest
|
|
@LargeTest
|
|
|
class BaselineProfileGenerator {
|
|
class BaselineProfileGenerator {
|
|
@@ -33,38 +39,46 @@ class BaselineProfileGenerator {
|
|
|
pressHome()
|
|
pressHome()
|
|
|
startActivityAndWait()
|
|
startActivityAndWait()
|
|
|
|
|
|
|
|
|
|
+ // 等书架加载完成。
|
|
|
val bookshelfSelector = By.desc("bookshelf_list")
|
|
val bookshelfSelector = By.desc("bookshelf_list")
|
|
|
device.wait(Until.hasObject(bookshelfSelector), 10000)
|
|
device.wait(Until.hasObject(bookshelfSelector), 10000)
|
|
|
-
|
|
|
|
|
device.waitForIdle()
|
|
device.waitForIdle()
|
|
|
Thread.sleep(2000)
|
|
Thread.sleep(2000)
|
|
|
|
|
|
|
|
- val screenWidth = device.displayWidth
|
|
|
|
|
- val screenHeight = device.displayHeight
|
|
|
|
|
- val startX = screenWidth / 2
|
|
|
|
|
- val startY = (screenHeight * 0.75).toInt()
|
|
|
|
|
- val endY = (screenHeight * 0.25).toInt()
|
|
|
|
|
|
|
+ val w = device.displayWidth
|
|
|
|
|
+ val h = device.displayHeight
|
|
|
|
|
|
|
|
- repeat(3) {
|
|
|
|
|
- device.swipe(startX, startY, startX, endY, 25)
|
|
|
|
|
- Thread.sleep(1000)
|
|
|
|
|
|
|
+ // 打开第一本书进入阅读器。
|
|
|
|
|
+ // 注意:开书前不要滑动书架——下滑会让顶栏展开、把书目挤下去,位置漂移点不中。
|
|
|
|
|
+ // 书目是 Compose 语义节点,uiautomator 中 clickable=false,UiObject2.click() 不可靠,
|
|
|
|
|
+ // 因此用「书特有的进度描述」(未读/已读/第N章)精确定位书节点,取其 bounds 中心,
|
|
|
|
|
+ // 用原始坐标点击(等价 input tap,最稳)。找不到时退回已验证的左上角书位坐标。
|
|
|
|
|
+ val bookMatcher = By.desc(Pattern.compile(".*(未读|已读|读到|第.{1,8}章).*"))
|
|
|
|
|
+ val bookNode = device.wait(Until.findObject(bookMatcher), 5000)
|
|
|
|
|
+ if (bookNode != null) {
|
|
|
|
|
+ val b = bookNode.visibleBounds
|
|
|
|
|
+ device.click(b.centerX(), b.centerY())
|
|
|
|
|
+ } else {
|
|
|
|
|
+ device.click((w * 0.18f).toInt(), (h * 0.37f).toInt())
|
|
|
}
|
|
}
|
|
|
|
|
+ device.waitForIdle()
|
|
|
|
|
+ Thread.sleep(3000)
|
|
|
|
|
+
|
|
|
|
|
+ // 若点书进的是书籍详情页,点“阅读”FAB 进入阅读器;已直接进阅读器则为 null,跳过。
|
|
|
|
|
+ device.wait(Until.findObject(By.text("阅读")), 2000)?.click()
|
|
|
|
|
+ device.waitForIdle()
|
|
|
|
|
+
|
|
|
|
|
+ // 等阅读器首屏排版完成。
|
|
|
|
|
+ Thread.sleep(3500)
|
|
|
|
|
|
|
|
- repeat(2) {
|
|
|
|
|
- device.swipe(startX, endY, startX, startY, 10)
|
|
|
|
|
- Thread.sleep(1000)
|
|
|
|
|
|
|
+ // 翻几页,顺带采样相邻章排版与翻页绘制。
|
|
|
|
|
+ repeat(4) {
|
|
|
|
|
+ device.swipe((w * 0.85f).toInt(), h / 2, (w * 0.15f).toInt(), h / 2, 8)
|
|
|
|
|
+ Thread.sleep(900)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // "nav_my"
|
|
|
|
|
- /* val tabs = listOf("nav_explore", "nav_rss", "nav_bookshelf")
|
|
|
|
|
- for (tabDesc in tabs) {
|
|
|
|
|
- val tab = device.wait(Until.findObject(By.desc(tabDesc)), 5000)
|
|
|
|
|
- if (tab != null) {
|
|
|
|
|
- val bounds = tab.visibleBounds
|
|
|
|
|
- device.click(bounds.centerX(), bounds.centerY())
|
|
|
|
|
- Thread.sleep(3000)
|
|
|
|
|
- }
|
|
|
|
|
- }*/
|
|
|
|
|
|
|
+ device.pressBack()
|
|
|
|
|
+ Thread.sleep(1500)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
|
|
+}
|