feat: add airtest scripts for camera and gallery testing
This commit is contained in:
@@ -76,6 +76,7 @@ import com.inspection.camera.util.PermissionManager
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
@@ -158,17 +159,17 @@ fun CameraScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取位置
|
// 获取位置(10秒超时)
|
||||||
LaunchedEffect(permissionsState.allPermissionsGranted, hasLocationPermission) {
|
LaunchedEffect(permissionsState.allPermissionsGranted, hasLocationPermission) {
|
||||||
isLocationLoading = true
|
isLocationLoading = true
|
||||||
if (permissionsState.allPermissionsGranted && hasLocationPermission) {
|
if (permissionsState.allPermissionsGranted && hasLocationPermission) {
|
||||||
try {
|
try {
|
||||||
Log.d("CameraScreen", "Getting location...")
|
Log.d("CameraScreen", "Getting location with 10s timeout...")
|
||||||
locationText = locationHelper.getLocationInfo()
|
val result = withTimeoutOrNull(10000) {
|
||||||
Log.d("CameraScreen", "Location result: $locationText")
|
locationHelper.getLocationInfo()
|
||||||
if (locationText.isEmpty()) {
|
|
||||||
locationText = "定位失败"
|
|
||||||
}
|
}
|
||||||
|
locationText = result ?: "定位失败"
|
||||||
|
Log.d("CameraScreen", "Location result: $locationText")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("CameraScreen", "Location error", e)
|
Log.e("CameraScreen", "Location error", e)
|
||||||
locationText = "定位失败"
|
locationText = "定位失败"
|
||||||
@@ -200,6 +201,9 @@ fun CameraScreen(
|
|||||||
onComplete = { uri ->
|
onComplete = { uri ->
|
||||||
capturedImages.add(uri)
|
capturedImages.add(uri)
|
||||||
isCapturing = false
|
isCapturing = false
|
||||||
|
},
|
||||||
|
onError = {
|
||||||
|
isCapturing = false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -299,7 +303,7 @@ private fun CameraContent(
|
|||||||
|
|
||||||
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cameraProvider.unbindAll()
|
cameraProvider.unbindAll()
|
||||||
cameraProvider.bindToLifecycle(
|
cameraProvider.bindToLifecycle(
|
||||||
lifecycleOwner,
|
lifecycleOwner,
|
||||||
@@ -307,8 +311,10 @@ private fun CameraContent(
|
|||||||
preview,
|
preview,
|
||||||
imageCapture
|
imageCapture
|
||||||
)
|
)
|
||||||
|
Log.d("CameraScreen", "Camera initialized successfully")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e("CameraScreen", "Camera binding failed", e)
|
Log.e("CameraScreen", "Camera binding failed", e)
|
||||||
|
imageCapture = null
|
||||||
}
|
}
|
||||||
}, ContextCompat.getMainExecutor(context))
|
}, ContextCompat.getMainExecutor(context))
|
||||||
|
|
||||||
@@ -462,24 +468,31 @@ private suspend fun getValidLocationTextForPhoto(
|
|||||||
manualAddress: String,
|
manualAddress: String,
|
||||||
locationHelper: LocationHelper
|
locationHelper: LocationHelper
|
||||||
): String {
|
): String {
|
||||||
|
Log.d("CameraScreen", "getValidLocationTextForPhoto called, currentLocationText=$currentLocationText")
|
||||||
|
|
||||||
// 检查当前定位文本是否有效
|
// 检查当前定位文本是否有效
|
||||||
val invalidTexts = listOf("正在定位...", "定位失败", "请授予定位权限")
|
val invalidTexts = listOf("正在定位...", "定位失败", "请授予定位权限")
|
||||||
val isInvalid = currentLocationText.isBlank() || invalidTexts.contains(currentLocationText)
|
val isInvalid = currentLocationText.isBlank() || invalidTexts.contains(currentLocationText)
|
||||||
|
|
||||||
if (!isInvalid) {
|
if (!isInvalid) {
|
||||||
|
Log.d("CameraScreen", "Using current location text: $currentLocationText")
|
||||||
return currentLocationText
|
return currentLocationText
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用手动地址
|
// 使用手动地址
|
||||||
if (manualAddress.isNotBlank()) {
|
if (manualAddress.isNotBlank()) {
|
||||||
|
Log.d("CameraScreen", "Using manual address: $manualAddress")
|
||||||
return manualAddress
|
return manualAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试快速获取当前位置(使用缓存)
|
// 尝试快速获取当前位置(使用缓存)
|
||||||
|
Log.d("CameraScreen", "Requesting new location...")
|
||||||
val location = locationHelper.getCurrentLocation()
|
val location = locationHelper.getCurrentLocation()
|
||||||
return location?.let {
|
val result = location?.let {
|
||||||
"${"%.4f".format(it.latitude)}, ${"%.4f".format(it.longitude)}"
|
"${"%.4f".format(it.latitude)}, ${"%.4f".format(it.longitude)}"
|
||||||
} ?: "未知地点"
|
} ?: "未知地点"
|
||||||
|
Log.d("CameraScreen", "Got location result: $result")
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun capturePhoto(
|
private fun capturePhoto(
|
||||||
@@ -489,8 +502,10 @@ private fun capturePhoto(
|
|||||||
watermarkStyle: WatermarkStyle,
|
watermarkStyle: WatermarkStyle,
|
||||||
imageQuality: ImageQuality,
|
imageQuality: ImageQuality,
|
||||||
locationText: String,
|
locationText: String,
|
||||||
onComplete: (Uri) -> Unit
|
onComplete: (Uri) -> Unit,
|
||||||
|
onError: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
|
Log.d("CameraScreen", "capturePhoto called, locationText=$locationText")
|
||||||
val photoFile = File(
|
val photoFile = File(
|
||||||
context.cacheDir,
|
context.cacheDir,
|
||||||
"photo_${System.currentTimeMillis()}.jpg"
|
"photo_${System.currentTimeMillis()}.jpg"
|
||||||
@@ -504,9 +519,17 @@ private fun capturePhoto(
|
|||||||
executor,
|
executor,
|
||||||
object : ImageCapture.OnImageSavedCallback {
|
object : ImageCapture.OnImageSavedCallback {
|
||||||
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
|
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
|
||||||
|
Log.d("CameraScreen", "Photo saved, adding watermark with locationText=$locationText")
|
||||||
val bitmap = BitmapFactory.decodeFile(photoFile.absolutePath)
|
val bitmap = BitmapFactory.decodeFile(photoFile.absolutePath)
|
||||||
if (bitmap != null) {
|
if (bitmap == null) {
|
||||||
|
Log.e("CameraScreen", "Failed to decode photo file: ${photoFile.absolutePath}")
|
||||||
|
onError()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
val timeText = ImageProcessor.getCurrentTimeText()
|
val timeText = ImageProcessor.getCurrentTimeText()
|
||||||
|
Log.d("CameraScreen", "Adding watermark: timeText=$timeText, locationText=$locationText")
|
||||||
val watermarkedBitmap = ImageProcessor.addWatermark(
|
val watermarkedBitmap = ImageProcessor.addWatermark(
|
||||||
bitmap,
|
bitmap,
|
||||||
timeText,
|
timeText,
|
||||||
@@ -521,12 +544,22 @@ private fun capturePhoto(
|
|||||||
bitmap.recycle()
|
bitmap.recycle()
|
||||||
watermarkedBitmap.recycle()
|
watermarkedBitmap.recycle()
|
||||||
|
|
||||||
uri?.let { onComplete(it) }
|
if (uri != null) {
|
||||||
|
onComplete(uri)
|
||||||
|
} else {
|
||||||
|
Log.e("CameraScreen", "Failed to save image to gallery")
|
||||||
|
onError()
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("CameraScreen", "Error processing image", e)
|
||||||
|
bitmap.recycle()
|
||||||
|
onError()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(exception: ImageCaptureException) {
|
override fun onError(exception: ImageCaptureException) {
|
||||||
Log.e("CameraScreen", "Photo capture failed", exception)
|
Log.e("CameraScreen", "Photo capture failed", exception)
|
||||||
|
onError()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ fun GalleryScreen(
|
|||||||
var selectedImages by remember { mutableStateOf<Set<Uri>>(emptySet()) }
|
var selectedImages by remember { mutableStateOf<Set<Uri>>(emptySet()) }
|
||||||
var showDeleteDialog by remember { mutableStateOf(false) }
|
var showDeleteDialog by remember { mutableStateOf(false) }
|
||||||
var isSelectionMode by remember { mutableStateOf(false) }
|
var isSelectionMode by remember { mutableStateOf(false) }
|
||||||
|
var selectedImageUri by remember { mutableStateOf<Uri?>(null) }
|
||||||
|
|
||||||
// 加载图片
|
// 加载图片
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
@@ -149,6 +150,9 @@ fun GalleryScreen(
|
|||||||
} else {
|
} else {
|
||||||
selectedImages + uri
|
selectedImages + uri
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// 非选择模式下,点击打开大图查看器
|
||||||
|
selectedImageUri = uri
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongClick = {
|
onLongClick = {
|
||||||
@@ -189,6 +193,32 @@ fun GalleryScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 大图查看对话框
|
||||||
|
if (selectedImageUri != null) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { selectedImageUri = null },
|
||||||
|
title = { Text("图片预览") },
|
||||||
|
text = {
|
||||||
|
AsyncImage(
|
||||||
|
model = ImageRequest.Builder(LocalContext.current)
|
||||||
|
.data(selectedImageUri)
|
||||||
|
.crossfade(true)
|
||||||
|
.build(),
|
||||||
|
contentDescription = "大图预览",
|
||||||
|
contentScale = ContentScale.Fit,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.aspectRatio(1f)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = { selectedImageUri = null }) {
|
||||||
|
Text("关闭")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
@@ -33,6 +33,44 @@ object ImageProcessor {
|
|||||||
private val dateFormat = SimpleDateFormat("yyyy年-MM月-dd日 HH:mm:ss", Locale.getDefault())
|
private val dateFormat = SimpleDateFormat("yyyy年-MM月-dd日 HH:mm:ss", Locale.getDefault())
|
||||||
private val fileNameFormat = SimpleDateFormat("yyyyMMddHHmm", Locale.getDefault())
|
private val fileNameFormat = SimpleDateFormat("yyyyMMddHHmm", Locale.getDefault())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试加载图片 Bitmap
|
||||||
|
*/
|
||||||
|
private fun tryLoadBitmap(context: Context, imageItem: ImageItem): Bitmap? {
|
||||||
|
android.util.Log.d("ImageProcessor", "Loading image, URI: ${imageItem.uri}, path: ${imageItem.path}")
|
||||||
|
|
||||||
|
// 优先尝试 URI 加载
|
||||||
|
try {
|
||||||
|
val uri = imageItem.uri
|
||||||
|
android.util.Log.d("ImageProcessor", "Trying to open URI: $uri")
|
||||||
|
context.contentResolver.openInputStream(uri)?.use { inputStream ->
|
||||||
|
val bitmap = BitmapFactory.decodeStream(inputStream)
|
||||||
|
android.util.Log.d("ImageProcessor", "URI loaded bitmap: ${bitmap != null}")
|
||||||
|
return bitmap
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
android.util.Log.e("ImageProcessor", "URI load failed: ${e.message}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 尝试从文件路径加载
|
||||||
|
if (imageItem.path.isNotEmpty()) {
|
||||||
|
try {
|
||||||
|
val file = java.io.File(imageItem.path)
|
||||||
|
android.util.Log.d("ImageProcessor", "Trying file: ${file.absolutePath}, exists: ${file.exists()}")
|
||||||
|
if (file.exists()) {
|
||||||
|
val bitmap = BitmapFactory.decodeFile(imageItem.path)
|
||||||
|
android.util.Log.d("ImageProcessor", "File loaded bitmap: ${bitmap != null}")
|
||||||
|
return bitmap
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
android.util.Log.e("ImageProcessor", "File load failed: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
android.util.Log.w("ImageProcessor", "Failed to load image")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前时间戳文本
|
* 获取当前时间戳文本
|
||||||
*/
|
*/
|
||||||
@@ -101,9 +139,10 @@ object ImageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 合成多张图片
|
* 合成多张图片(支持 URI)
|
||||||
*/
|
*/
|
||||||
fun mergeImages(
|
fun mergeImages(
|
||||||
|
context: Context,
|
||||||
images: List<ImageItem>,
|
images: List<ImageItem>,
|
||||||
layoutType: MergeLayoutType,
|
layoutType: MergeLayoutType,
|
||||||
quality: ImageQuality
|
quality: ImageQuality
|
||||||
@@ -114,7 +153,6 @@ object ImageProcessor {
|
|||||||
|
|
||||||
val cols = layoutType.cols
|
val cols = layoutType.cols
|
||||||
val rows = layoutType.rows
|
val rows = layoutType.rows
|
||||||
val imageCount = images.size.coerceAtMost(rows * cols)
|
|
||||||
|
|
||||||
val outputWidth = 1920
|
val outputWidth = 1920
|
||||||
val outputHeight = 1080
|
val outputHeight = 1080
|
||||||
@@ -137,10 +175,10 @@ object ImageProcessor {
|
|||||||
val top = row * cellHeight
|
val top = row * cellHeight
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val sourceBitmap = BitmapFactory.decodeFile(imageItem.path)
|
val sourceBitmap = tryLoadBitmap(context, imageItem)
|
||||||
?: return@forEachIndexed
|
|
||||||
|
sourceBitmap ?: return@forEachIndexed
|
||||||
|
|
||||||
// 缩放并居中裁剪
|
|
||||||
val scaledBitmap = scaleAndCropBitmap(sourceBitmap, cellWidth, cellHeight)
|
val scaledBitmap = scaleAndCropBitmap(sourceBitmap, cellWidth, cellHeight)
|
||||||
val dstRect = Rect(left, top, left + cellWidth, top + cellHeight)
|
val dstRect = Rect(left, top, left + cellWidth, top + cellHeight)
|
||||||
canvas.drawBitmap(scaledBitmap, null, dstRect, paint)
|
canvas.drawBitmap(scaledBitmap, null, dstRect, paint)
|
||||||
@@ -150,7 +188,6 @@ object ImageProcessor {
|
|||||||
}
|
}
|
||||||
sourceBitmap.recycle()
|
sourceBitmap.recycle()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
// 加载失败绘制占位
|
|
||||||
val placeholderPaint = Paint().apply {
|
val placeholderPaint = Paint().apply {
|
||||||
color = Color.LTGRAY
|
color = Color.LTGRAY
|
||||||
}
|
}
|
||||||
|
|||||||
116
test_android.py
Normal file
116
test_android.py
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Android 模拟器图像识别测试脚本
|
||||||
|
"""
|
||||||
|
from airtest.core.api import *
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# 初始化设备连接
|
||||||
|
def init_device():
|
||||||
|
# 连接 Android 模拟器
|
||||||
|
dev = connect_device("android://127.0.0.1:5037/emulator-5554")
|
||||||
|
print(f"已连接设备: {dev}")
|
||||||
|
return dev
|
||||||
|
|
||||||
|
# 截取当前屏幕
|
||||||
|
def capture_screen(filename="screen.png"):
|
||||||
|
dev = device()
|
||||||
|
screen = dev.snapshot()
|
||||||
|
|
||||||
|
# numpy.ndarray 转换为 PIL Image 并保存
|
||||||
|
from PIL import Image
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
img = Image.fromarray(screen)
|
||||||
|
img.save(filename)
|
||||||
|
print(f"截图已保存: {filename}")
|
||||||
|
return screen
|
||||||
|
|
||||||
|
# 测试1: 打开相机应用
|
||||||
|
def test_open_camera():
|
||||||
|
print("测试1: 打开相机应用...")
|
||||||
|
|
||||||
|
# 使用 ADB 启动相机
|
||||||
|
shell("am start -n com.inspection.camera/.ui.MainActivity")
|
||||||
|
sleep(2)
|
||||||
|
|
||||||
|
# 截图
|
||||||
|
capture_screen("test_open_camera.png")
|
||||||
|
print("相机已打开")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 测试2: 模拟点击屏幕中心(测试触摸功能)
|
||||||
|
def test_touch():
|
||||||
|
print("测试2: 测试触摸功能...")
|
||||||
|
|
||||||
|
# 点击屏幕中心
|
||||||
|
touch([540, 960]) # 模拟器分辨率 1080x1920 的中心点
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
capture_screen("test_touch.png")
|
||||||
|
print("触摸测试完成")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 测试3: 滑动测试
|
||||||
|
def test_swipe():
|
||||||
|
print("测试3: 测试滑动功能...")
|
||||||
|
|
||||||
|
# 从上往下滑动
|
||||||
|
swipe([540, 300], [540, 900])
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
capture_screen("test_swipe.png")
|
||||||
|
print("滑动测试完成")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 测试4: 查找屏幕上是否有特定文字(使用OCR)
|
||||||
|
def test_ocr():
|
||||||
|
print("测试4: OCR文字识别测试...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
from airtest.aircv import aircv
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
# 截图
|
||||||
|
screen = device().snapshot()
|
||||||
|
|
||||||
|
# 使用 PIL 显示图像信息
|
||||||
|
from PIL import Image
|
||||||
|
img = Image.fromarray(screen)
|
||||||
|
print(f"屏幕分辨率: {img.size}")
|
||||||
|
print(f"屏幕模式: {img.mode}")
|
||||||
|
|
||||||
|
capture_screen("test_ocr.png")
|
||||||
|
print("OCR 测试完成")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"OCR测试出错: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 主测试函数
|
||||||
|
def main():
|
||||||
|
print("=" * 50)
|
||||||
|
print("Android 模拟器图像识别测试")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 初始化设备
|
||||||
|
init_device()
|
||||||
|
|
||||||
|
# 执行测试
|
||||||
|
test_open_camera()
|
||||||
|
test_touch()
|
||||||
|
test_swipe()
|
||||||
|
test_ocr()
|
||||||
|
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
print("所有测试完成!")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"测试出错: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
116
test_camera.py
Normal file
116
test_camera.py
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import sys
|
||||||
|
import io
|
||||||
|
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
|
||||||
|
|
||||||
|
"""
|
||||||
|
测试拍照功能
|
||||||
|
"""
|
||||||
|
from airtest.core.api import *
|
||||||
|
from PIL import Image
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
def init_device():
|
||||||
|
# dev = connect_device("android://127.0.0.1:5037/emulator-5554") # 模拟器
|
||||||
|
dev = connect_device("android://127.0.0.1:5037/APH0219A29002701") # 真机
|
||||||
|
print(f"已连接设备: {dev}")
|
||||||
|
return dev
|
||||||
|
|
||||||
|
def capture_screen(filename="screen.png"):
|
||||||
|
screen = device().snapshot()
|
||||||
|
img = Image.fromarray(screen)
|
||||||
|
img.save(filename)
|
||||||
|
print(f"截图已保存: {filename}")
|
||||||
|
return screen
|
||||||
|
|
||||||
|
def test_camera():
|
||||||
|
print("=" * 50)
|
||||||
|
print("测试:拍照功能")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
# 启动相机应用
|
||||||
|
print("1. 启动相机应用...")
|
||||||
|
shell("am start -n com.inspection.camera/.ui.MainActivity")
|
||||||
|
sleep(3)
|
||||||
|
|
||||||
|
capture_screen("01_app_loaded.png")
|
||||||
|
print(" 相机应用已启动")
|
||||||
|
|
||||||
|
# 点击拍照按钮 (屏幕底部中央 - 2400高,底部区域约在2200)
|
||||||
|
print("2. 点击拍照按钮...")
|
||||||
|
touch([540, 2200]) # 拍照按钮位置
|
||||||
|
sleep(3)
|
||||||
|
|
||||||
|
capture_screen("02_after_capture.png")
|
||||||
|
print(" 拍照完成")
|
||||||
|
|
||||||
|
# 检查照片是否生成
|
||||||
|
print("3. 检查照片是否生成...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 创建Pictures目录(如果不存在)
|
||||||
|
shell("mkdir -p /storage/emulated/0/Pictures/inspection")
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
# 列出Pictures目录下的文件
|
||||||
|
result = shell("ls -la /storage/emulated/0/Pictures/inspection/")
|
||||||
|
print(f" Pictures目录内容: {result}")
|
||||||
|
|
||||||
|
# 检查是否有新的照片文件
|
||||||
|
files_output = shell("ls /storage/emulated/0/Pictures/inspection/").strip()
|
||||||
|
|
||||||
|
if files_output and "No such file" not in files_output:
|
||||||
|
files = files_output.split('\n')
|
||||||
|
print(f" 照片文件列表: {files}")
|
||||||
|
|
||||||
|
if files and files[0]:
|
||||||
|
latest_photo = files[-1].strip()
|
||||||
|
print(f" [OK] 照片已生成: {latest_photo}")
|
||||||
|
|
||||||
|
# 拉取最新照片到本地
|
||||||
|
pull_cmd = f"/storage/emulated/0/Pictures/inspection/{latest_photo}"
|
||||||
|
os.system(f'"C:\\Users\\xiaji\\AppData\\Local\\Android\\Sdk\\platform-tools\\adb.exe" -s emulator-5554 pull "{pull_cmd}" . 2>nul')
|
||||||
|
|
||||||
|
if os.path.exists(latest_photo):
|
||||||
|
print(f" [OK] 照片已保存到本地: {latest_photo}")
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
print("测试结果: 拍照功能正常!")
|
||||||
|
print("=" * 50)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(" [X] 照片未保存到本地")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print(" [X] 未找到照片文件")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
# 检查DCIM目录
|
||||||
|
dcim_result = shell("ls /storage/emulated/0/DCIM/Camera/")
|
||||||
|
print(f" DCIM目录内容: {dcim_result}")
|
||||||
|
if dcim_result and "No such file" not in dcim_result and dcim_result.strip():
|
||||||
|
print(f" [OK] 照片已生成在DCIM目录")
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
print("测试结果: 拍照功能正常!")
|
||||||
|
print("=" * 50)
|
||||||
|
return True
|
||||||
|
|
||||||
|
print(" [X] 未找到任何照片")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f" [X] 检查照片时出错: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
init_device()
|
||||||
|
result = test_camera()
|
||||||
|
if result:
|
||||||
|
print("\n测试通过!")
|
||||||
|
else:
|
||||||
|
print("\n测试失败!")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"测试出错: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
57
test_gallery.py
Normal file
57
test_gallery.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Gallery Test - Test if clicking thumbnail opens full image
|
||||||
|
"""
|
||||||
|
from airtest.core.api import *
|
||||||
|
from PIL import Image
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
def init_device():
|
||||||
|
dev = connect_device("android://127.0.0.1:5037/emulator-5554")
|
||||||
|
print(f"Device connected")
|
||||||
|
return dev
|
||||||
|
|
||||||
|
def capture_screen(filename="screen.png"):
|
||||||
|
screen = device().snapshot()
|
||||||
|
img = Image.fromarray(screen)
|
||||||
|
img.save(filename)
|
||||||
|
print(f"Screenshot: {filename}")
|
||||||
|
return screen
|
||||||
|
|
||||||
|
# Main
|
||||||
|
print("=" * 50)
|
||||||
|
print("Gallery Test - Click Thumbnail")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
init_device()
|
||||||
|
sleep(2)
|
||||||
|
|
||||||
|
# Go to gallery tab
|
||||||
|
touch([270, 2300]) # Gallery tab
|
||||||
|
sleep(3)
|
||||||
|
capture_screen("gallery1_main.png")
|
||||||
|
|
||||||
|
# Click on first thumbnail (latest image)
|
||||||
|
touch([540, 600])
|
||||||
|
sleep(2)
|
||||||
|
capture_screen("gallery2_after_click.png")
|
||||||
|
|
||||||
|
# Check if screen changed (full image viewer opened)
|
||||||
|
# Compare two screenshots
|
||||||
|
img1 = np.array(Image.open("gallery1_main.png"))
|
||||||
|
img2 = np.array(Image.open("gallery2_after_click.png"))
|
||||||
|
|
||||||
|
# Calculate similarity
|
||||||
|
diff = np.abs(img1.astype(float) - img2.astype(float)).mean()
|
||||||
|
print(f"Screen difference: {diff:.2f}")
|
||||||
|
|
||||||
|
# Check if there's any UI change
|
||||||
|
# If diff > 50, it means screen changed significantly
|
||||||
|
if diff > 50:
|
||||||
|
print("RESULT: Screen changed after clicking thumbnail")
|
||||||
|
print(" (Full image viewer may have opened)")
|
||||||
|
else:
|
||||||
|
print("RESULT: Screen did NOT change after clicking thumbnail")
|
||||||
|
print(" (Click is NOT working - BUG!)")
|
||||||
|
|
||||||
|
print("=" * 50)
|
||||||
63
test_gallery_thumbnail.py
Normal file
63
test_gallery_thumbnail.py
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Gallery Test - Test clicking thumbnail to view full image
|
||||||
|
"""
|
||||||
|
from airtest.core.api import *
|
||||||
|
from PIL import Image
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
def init_device():
|
||||||
|
dev = connect_device("android://127.0.0.1:5037/emulator-5554")
|
||||||
|
print(f"Device connected")
|
||||||
|
return dev
|
||||||
|
|
||||||
|
def capture_screen(filename="screen.png"):
|
||||||
|
screen = device().snapshot()
|
||||||
|
img = Image.fromarray(screen)
|
||||||
|
img.save(filename)
|
||||||
|
print(f"Screenshot: {filename}")
|
||||||
|
return screen
|
||||||
|
|
||||||
|
def calculate_similarity(img1_path, img2_path):
|
||||||
|
img1 = np.array(Image.open(img1_path))
|
||||||
|
img2 = np.array(Image.open(img2_path))
|
||||||
|
diff = np.abs(img1.astype(float) - img2.astype(float)).mean()
|
||||||
|
return diff
|
||||||
|
|
||||||
|
print("=" * 50)
|
||||||
|
print("Gallery Test - Click Thumbnail to View Full Image")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
init_device()
|
||||||
|
sleep(2)
|
||||||
|
|
||||||
|
# Step 1: Open Gallery app
|
||||||
|
print("Step 1: Open Gallery app")
|
||||||
|
touch([270, 2300]) # Gallery tab
|
||||||
|
sleep(3)
|
||||||
|
capture_screen("gallery_home.png")
|
||||||
|
|
||||||
|
# Step 2: Verify thumbnails are displayed
|
||||||
|
print("Step 2: Verify thumbnails are displayed")
|
||||||
|
thumbnails_visible = exists(Template(r"tpl_thumbnail.png"))
|
||||||
|
print(f"Thumbnails visible: {thumbnails_visible}")
|
||||||
|
|
||||||
|
# Step 3: Click on a thumbnail to view full image
|
||||||
|
print("Step 3: Click on first thumbnail")
|
||||||
|
touch([540, 600]) # First thumbnail position
|
||||||
|
sleep(2)
|
||||||
|
capture_screen("full_image.png")
|
||||||
|
|
||||||
|
# Step 4: Verify full image viewer opened
|
||||||
|
print("Step 4: Verify full image viewer opened")
|
||||||
|
diff = calculate_similarity("gallery_home.png", "full_image.png")
|
||||||
|
print(f"Screen difference: {diff:.2f}")
|
||||||
|
|
||||||
|
# Step 5: Test result
|
||||||
|
print("=" * 50)
|
||||||
|
if diff > 50:
|
||||||
|
print("PASS: Clicking thumbnail opens full image viewer")
|
||||||
|
else:
|
||||||
|
print("FAIL: Clicking thumbnail does NOT open full image")
|
||||||
|
print(" (This is a BUG - thumbnail click is not working)")
|
||||||
|
print("=" * 50)
|
||||||
113
test_location_watermark.py
Normal file
113
test_location_watermark.py
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from airtest.core.api import *
|
||||||
|
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
|
||||||
|
import time
|
||||||
|
|
||||||
|
# 初始化设备
|
||||||
|
init_device("Android", uuid="emulator-5554")
|
||||||
|
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)
|
||||||
|
|
||||||
|
print("=" * 50)
|
||||||
|
print("开始测试拍照功能 - 位置水印测试")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
# 启动应用
|
||||||
|
print("\n[1] 启动应用...")
|
||||||
|
home()
|
||||||
|
start_app("com.inspection.camera")
|
||||||
|
sleep(5)
|
||||||
|
|
||||||
|
# 等待应用加载
|
||||||
|
print("[2] 等待应用加载...")
|
||||||
|
snapshot("app_loaded.png")
|
||||||
|
print("[INFO] 已保存截图: app_loaded.png")
|
||||||
|
|
||||||
|
# 等待定位完成,检测定位文本
|
||||||
|
print("\n[3] 等待定位完成(最多15秒)...")
|
||||||
|
location_text = ""
|
||||||
|
for i in range(15):
|
||||||
|
try:
|
||||||
|
# 尝试通过poco获取定位文本(UI中的卡片文本)
|
||||||
|
# 定位文本可能位于某个Card内,我们尝试查找包含"定位"的文本元素
|
||||||
|
elements = poco(textMatches=".*定位.*")
|
||||||
|
if elements.exists():
|
||||||
|
location_text = elements.get_text()
|
||||||
|
print(f"[INFO] 检测到定位文本: {location_text}")
|
||||||
|
if location_text != "正在定位...":
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
sleep(1)
|
||||||
|
print(f"等待 {i+1}/15 秒")
|
||||||
|
|
||||||
|
# 如果未找到定位文本,尝试其他选择器
|
||||||
|
if not location_text:
|
||||||
|
try:
|
||||||
|
# 尝试查找包含"定位"或"位置"的文本
|
||||||
|
for text in ["定位", "位置", "地点"]:
|
||||||
|
elements = poco(textMatches=f".*{text}.*")
|
||||||
|
if elements.exists():
|
||||||
|
location_text = elements.get_text()
|
||||||
|
print(f"[INFO] 通过关键词 '{text}' 找到定位文本: {location_text}")
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[WARNING] 查找定位文本失败: {e}")
|
||||||
|
|
||||||
|
print(f"\n[INFO] 最终定位文本: '{location_text}'")
|
||||||
|
|
||||||
|
# 验证定位是否失败(超时后应显示"定位失败")
|
||||||
|
if location_text == "定位失败":
|
||||||
|
print("[SUCCESS] 定位超时后正确显示'定位失败'")
|
||||||
|
else:
|
||||||
|
print(f"[WARNING] 定位文本不是'定位失败',而是: {location_text}")
|
||||||
|
|
||||||
|
# 点击拍照按钮(屏幕中央下方)
|
||||||
|
print("\n[4] 点击拍照按钮...")
|
||||||
|
shell("input tap 540 2100")
|
||||||
|
sleep(3)
|
||||||
|
snapshot("after_capture.png")
|
||||||
|
print("[INFO] 拍照后截图: after_capture.png")
|
||||||
|
|
||||||
|
# 检查保存的图片文件
|
||||||
|
print("\n[4.5] 检查保存的图片文件...")
|
||||||
|
sleep(2) # 等待文件保存
|
||||||
|
# 列出图片目录
|
||||||
|
output = shell("ls -t /sdcard/Pictures/InspectionCamera/*.jpg 2>/dev/null | head -1")
|
||||||
|
if output and output.strip():
|
||||||
|
latest_image = output.strip()
|
||||||
|
print(f"[INFO] 找到最新图片: {latest_image}")
|
||||||
|
# 获取文件大小
|
||||||
|
size_output = shell(f"du -h {latest_image} 2>/dev/null | cut -f1")
|
||||||
|
if size_output:
|
||||||
|
print(f"[INFO] 文件大小: {size_output.strip()}")
|
||||||
|
else:
|
||||||
|
print("[WARNING] 未找到保存的图片文件,可能路径不同")
|
||||||
|
# 尝试其他可能路径
|
||||||
|
shell("ls -l /sdcard/Pictures/ 2>/dev/null")
|
||||||
|
shell("ls -l /sdcard/DCIM/ 2>/dev/null")
|
||||||
|
|
||||||
|
# 打开相册
|
||||||
|
print("\n[5] 打开相册...")
|
||||||
|
shell("am start -n com.google.android.apps.photos/.home.HomeActivity")
|
||||||
|
sleep(3)
|
||||||
|
snapshot("gallery.png")
|
||||||
|
print("[INFO] 相册截图: gallery.png")
|
||||||
|
|
||||||
|
# 点击最新图片(假设第一张缩略图位于屏幕中央)
|
||||||
|
print("\n[6] 点击最新图片...")
|
||||||
|
touch([540, 600])
|
||||||
|
sleep(2)
|
||||||
|
snapshot("gallery_detail.png")
|
||||||
|
print("[INFO] 图片详情截图: gallery_detail.png")
|
||||||
|
|
||||||
|
print("\n[7] 测试完成,请检查截图文件中的水印")
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
print("测试完成!")
|
||||||
|
print("=" * 50)
|
||||||
|
print("\n请检查截图文件:")
|
||||||
|
print("1. app_loaded.png - 应用界面")
|
||||||
|
print("2. after_capture.png - 拍照后")
|
||||||
|
print("3. gallery.png - 相册")
|
||||||
|
print("4. gallery_detail.png - 图片详情")
|
||||||
|
print("\n检查照片左下角是否有时间+位置水印")
|
||||||
|
print("=" * 50)
|
||||||
227
test_puzzle.py
Normal file
227
test_puzzle.py
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Puzzle/Merge Function Test Script
|
||||||
|
Test flow:
|
||||||
|
1. Click "Puzzle" in bottom navigation
|
||||||
|
2. Select 2x2 layout
|
||||||
|
3. Select 4 images
|
||||||
|
4. Click "Preview"
|
||||||
|
5. Confirm merge result
|
||||||
|
6. Return to main page
|
||||||
|
7. Enter gallery
|
||||||
|
8. Check latest merge result
|
||||||
|
"""
|
||||||
|
from airtest.core.api import *
|
||||||
|
from PIL import Image
|
||||||
|
import numpy as np
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Initialize device
|
||||||
|
def init_device():
|
||||||
|
dev = connect_device("android://127.0.0.1:5037/emulator-5554")
|
||||||
|
print(f"Device connected: {dev}")
|
||||||
|
return dev
|
||||||
|
|
||||||
|
# Capture screen
|
||||||
|
def capture_screen(filename="screen.png"):
|
||||||
|
screen = device().snapshot()
|
||||||
|
img = Image.fromarray(screen)
|
||||||
|
img.save(filename)
|
||||||
|
print(f"Screenshot saved: {filename}")
|
||||||
|
return screen
|
||||||
|
|
||||||
|
# Wait for app launch
|
||||||
|
def wait_app_launch():
|
||||||
|
print("Waiting for app launch...")
|
||||||
|
sleep(3)
|
||||||
|
|
||||||
|
# Test 1: Click "Puzzle" tab in bottom navigation
|
||||||
|
def click_merge_tab():
|
||||||
|
print("Test 1: Click 'Puzzle' tab...")
|
||||||
|
# Bottom navigation: Camera(0), Gallery(1), Puzzle(2), Settings(3)
|
||||||
|
# Click puzzle button at bottom right
|
||||||
|
touch([810, 2300])
|
||||||
|
sleep(2)
|
||||||
|
capture_screen("01_click_merge.png")
|
||||||
|
print("Clicked puzzle")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Test 2: Select 2x2 layout
|
||||||
|
def select_2x2_layout():
|
||||||
|
print("Test 2: Select 2x2 layout...")
|
||||||
|
touch([180, 200])
|
||||||
|
sleep(1)
|
||||||
|
capture_screen("02_select_2x2.png")
|
||||||
|
print("Selected 2x2 layout")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Test 3: Select 4 images
|
||||||
|
def select_4_images():
|
||||||
|
print("Test 3: Select 4 images...")
|
||||||
|
|
||||||
|
# Click add image button (first empty cell)
|
||||||
|
touch([270, 500])
|
||||||
|
sleep(2)
|
||||||
|
|
||||||
|
# This will open system image picker
|
||||||
|
capture_screen("03_before_select_image.png")
|
||||||
|
|
||||||
|
# Click "Gallery" option
|
||||||
|
touch([540, 800])
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
# Select first image
|
||||||
|
touch([200, 400])
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
# Second image
|
||||||
|
touch([540, 400])
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
# Third image
|
||||||
|
touch([880, 400])
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
# Fourth image
|
||||||
|
touch([200, 700])
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
# Confirm selection (click OK button)
|
||||||
|
touch([900, 2300])
|
||||||
|
sleep(2)
|
||||||
|
|
||||||
|
capture_screen("04_selected_4_images.png")
|
||||||
|
print("Selected 4 images")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Test 4: Click preview button
|
||||||
|
def click_preview_button():
|
||||||
|
print("Test 4: Click preview button...")
|
||||||
|
touch([300, 2200])
|
||||||
|
sleep(3)
|
||||||
|
capture_screen("05_preview.png")
|
||||||
|
print("Clicked preview")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Test 5: Close preview dialog
|
||||||
|
def close_preview():
|
||||||
|
print("Test 5: Close preview dialog...")
|
||||||
|
touch([540, 1500])
|
||||||
|
sleep(1)
|
||||||
|
capture_screen("06_preview_closed.png")
|
||||||
|
print("Closed preview")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Test 6: Click save button
|
||||||
|
def click_save_button():
|
||||||
|
print("Test 6: Click save button...")
|
||||||
|
touch([800, 2200])
|
||||||
|
sleep(2)
|
||||||
|
capture_screen("07_save_dialog.png")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Test 7: Confirm save
|
||||||
|
def confirm_save():
|
||||||
|
print("Test 7: Confirm save...")
|
||||||
|
touch([700, 1400])
|
||||||
|
sleep(3)
|
||||||
|
capture_screen("08_saved.png")
|
||||||
|
print("Saved")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Test 8: Return to home page
|
||||||
|
def go_back_home():
|
||||||
|
print("Test 8: Return to home page...")
|
||||||
|
touch([100, 100])
|
||||||
|
sleep(2)
|
||||||
|
capture_screen("09_back_home.png")
|
||||||
|
print("Returned to home")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Test 9: Click "Gallery" tab
|
||||||
|
def click_gallery_tab():
|
||||||
|
print("Test 9: Click 'Gallery' tab...")
|
||||||
|
touch([270, 2300])
|
||||||
|
sleep(3)
|
||||||
|
capture_screen("10_gallery.png")
|
||||||
|
print("Clicked gallery")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Test 10: View latest image
|
||||||
|
def view_latest_image():
|
||||||
|
print("Test 10: View latest image...")
|
||||||
|
touch([540, 600])
|
||||||
|
sleep(2)
|
||||||
|
capture_screen("11_latest_image.png")
|
||||||
|
print("Opened latest image")
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 测试11: 检查图片是否为纯白色
|
||||||
|
def check_white_image():
|
||||||
|
print("Test 11: Check if image is pure white...")
|
||||||
|
|
||||||
|
# 读取截图
|
||||||
|
img = Image.open("11_latest_image.png")
|
||||||
|
img_array = np.array(img)
|
||||||
|
|
||||||
|
# 检查是否为纯白色 (RGB都接近255)
|
||||||
|
# 取图片中心区域进行判断
|
||||||
|
h, w = img_array.shape[:2]
|
||||||
|
center_region = img_array[h//4:3*h//4, w//4:3*w//4]
|
||||||
|
|
||||||
|
# 计算平均颜色
|
||||||
|
avg_color = np.mean(center_region, axis=(0, 1))
|
||||||
|
print(f"Image center average color: {avg_color}")
|
||||||
|
|
||||||
|
# 判断是否接近白色 (R, G, B 都 > 250)
|
||||||
|
is_white = all(c > 250 for c in avg_color[:3])
|
||||||
|
|
||||||
|
if is_white:
|
||||||
|
print("WARNING: Image is pure white, merge function may not work!")
|
||||||
|
else:
|
||||||
|
print("OK: Image is not pure white, merge function works")
|
||||||
|
|
||||||
|
return not is_white
|
||||||
|
|
||||||
|
# Main test function
|
||||||
|
def main():
|
||||||
|
print("=" * 60)
|
||||||
|
print("Puzzle/Merge Function Automated Test")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Initialize device
|
||||||
|
init_device()
|
||||||
|
|
||||||
|
# Wait for app launch
|
||||||
|
wait_app_launch()
|
||||||
|
|
||||||
|
# Execute test steps
|
||||||
|
click_merge_tab()
|
||||||
|
select_2x2_layout()
|
||||||
|
select_4_images()
|
||||||
|
click_preview_button()
|
||||||
|
close_preview()
|
||||||
|
click_save_button()
|
||||||
|
confirm_save()
|
||||||
|
go_back_home()
|
||||||
|
click_gallery_tab()
|
||||||
|
view_latest_image()
|
||||||
|
|
||||||
|
# Check result
|
||||||
|
result = check_white_image()
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
if result:
|
||||||
|
print("TEST PASSED! Merge function works normally")
|
||||||
|
else:
|
||||||
|
print("TEST FAILED! Merge result is pure white")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Test error: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
89
test_simple.py
Normal file
89
test_simple.py
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Simple test to verify merge works
|
||||||
|
"""
|
||||||
|
from airtest.core.api import *
|
||||||
|
from PIL import Image
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
def init_device():
|
||||||
|
dev = connect_device("android://127.0.0.1:5037/emulator-5554")
|
||||||
|
print(f"Device connected")
|
||||||
|
return dev
|
||||||
|
|
||||||
|
def capture_screen(filename="screen.png"):
|
||||||
|
screen = device().snapshot()
|
||||||
|
img = Image.fromarray(screen)
|
||||||
|
img.save(filename)
|
||||||
|
print(f"Screenshot: {filename}")
|
||||||
|
return screen
|
||||||
|
|
||||||
|
# Main
|
||||||
|
print("=" * 50)
|
||||||
|
print("Simple Merge Test")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
init_device()
|
||||||
|
sleep(2)
|
||||||
|
|
||||||
|
# Go to merge screen
|
||||||
|
touch([810, 2300]) # Puzzle tab
|
||||||
|
sleep(2)
|
||||||
|
capture_screen("step1_merge.png")
|
||||||
|
|
||||||
|
# Select 2x2
|
||||||
|
touch([180, 200])
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
# Add images
|
||||||
|
touch([270, 500])
|
||||||
|
sleep(2)
|
||||||
|
|
||||||
|
# Select 4 images from gallery
|
||||||
|
touch([540, 800]) # Gallery tab in picker
|
||||||
|
sleep(1)
|
||||||
|
touch([200, 400]) # Image 1
|
||||||
|
sleep(0.5)
|
||||||
|
touch([540, 400]) # Image 2
|
||||||
|
sleep(0.5)
|
||||||
|
touch([880, 400]) # Image 3
|
||||||
|
sleep(0.5)
|
||||||
|
touch([200, 700]) # Image 4
|
||||||
|
sleep(0.5)
|
||||||
|
touch([900, 2300]) # Confirm
|
||||||
|
sleep(2)
|
||||||
|
|
||||||
|
capture_screen("step2_selected.png")
|
||||||
|
|
||||||
|
# Click preview
|
||||||
|
touch([300, 2200]) # Preview button
|
||||||
|
sleep(3)
|
||||||
|
|
||||||
|
capture_screen("step3_preview.png")
|
||||||
|
|
||||||
|
# Check preview result
|
||||||
|
img = Image.open("step3_preview.png")
|
||||||
|
img_array = np.array(img)
|
||||||
|
h, w = img_array.shape[:2]
|
||||||
|
center_region = img_array[h//4:3*h//4, w//4:3*w//4]
|
||||||
|
avg_color = np.mean(center_region, axis=(0, 1))
|
||||||
|
print(f"Preview average color: {avg_color}")
|
||||||
|
|
||||||
|
# Close preview
|
||||||
|
touch([540, 1500])
|
||||||
|
sleep(1)
|
||||||
|
|
||||||
|
# Save
|
||||||
|
touch([800, 2200]) # Save button
|
||||||
|
sleep(2)
|
||||||
|
touch([700, 1400]) # Confirm save
|
||||||
|
sleep(3)
|
||||||
|
|
||||||
|
capture_screen("step4_saved.png")
|
||||||
|
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
if avg_color[0] < 250 and avg_color[1] < 250 and avg_color[2] < 250:
|
||||||
|
print("RESULT: Merge works! Preview shows merged images.")
|
||||||
|
else:
|
||||||
|
print("RESULT: Merge may have issues.")
|
||||||
|
print("=" * 50)
|
||||||
Reference in New Issue
Block a user