You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用Appium自动化测试实现经纬度定位地图中心并点击对应标记点?

如何使用Appium自动化测试实现经纬度定位地图中心并点击对应标记点?

嘿,我刚好有过用Appium+WebdriverIO做地图自动化测试的实战经验,结合你提到的技术栈(WebdriverIO v9、Appium v3),给你整理几个靠谱的落地方案,亲测在Android(UiAutomator2)和iOS(XCUITest)上都能跑通:

一、把地图定位到指定经纬度

这部分优先选最省心的方案,不行再降级到手势操作:

方案1:直接设置系统地理定位(最推荐,若地图支持)

有些主流地图SDK(比如Google Maps、高德/百度)会监听系统的位置变化,Appium的setGeoLocation接口可以直接模拟设备位置,地图会自动把中心跳到目标坐标,这是效率最高的方法。

TypeScript代码示例:

// 先确保你的capabilities已经开启了位置模拟权限
// Android在capabilities里加:autoGrantPermissions: true,或者手动授予位置权限
// iOS在capabilities里加:allowSimulatorLocationSimulation: true

async function setMapCenter(lat: number, lng: number) {
  await browser.setGeoLocation({
    latitude: lat,
    longitude: lng,
    altitude: 0 // 海拔一般设0就行,不影响地图中心
  });
  // 等待地图加载完成
  await browser.pause(1000);
  // 可以再加个缩放,确保标记点清晰
  const mapElement = await $('//android.view.View[@content-desc="map"]'); // 替换成你App的地图元素定位符
  await mapElement.pinchToZoom({ scale: 2, duration: 1000 }); // 放大2倍,持续1秒
}

注意:如果你的地图不响应系统位置变化(比如自研的地图SDK),这个方法就失效,得用下面的手势方案。

方案2:通过手势拖拽定位(兼容所有地图)

如果直接设置location不行,就用WebdriverIO的手势API来拖拽地图。这里的思路是:先把地图放大到最大级别(减少拖拽次数),然后通过多次拖拽把目标坐标移到屏幕中心。

不过更精准的方式是,如果你能拿到地图的投影参数(比如当前缩放级别、中心点坐标),可以计算出目标坐标和当前中心的像素差,然后直接拖拽对应的距离。如果拿不到这些参数,也可以用“盲拖”的方式(适合测试环境地图数据固定的情况):

async function panToCoordinates(lat: number, lng: number) {
  const mapElement = await $('//android.view.View[@content-desc="map"]'); // 替换成你的地图元素
  // 先放大到最大,确保标记点足够大
  await mapElement.pinchToZoom({ scale: 3, duration: 1500 });
  await browser.pause(500);

  // 假设我们知道目标坐标在当前地图的左上方,拖拽对应的距离
  // dragAndDrop的参数是目标元素或坐标,这里用相对坐标
  await mapElement.dragAndDrop({ x: 200, y: 200 }, { duration: 1000 });
  // 可以根据实际情况调整拖拽的x/y值,或者多次拖拽
  await browser.pause(500);
}

方案3:经纬度转屏幕坐标(需要开发配合)

如果是自家公司的App,可以让开发同学在测试环境暴露一个测试接口,直接把经纬度转换成屏幕上的x/y坐标。比如在App的测试入口加个方法:

// 假设开发给了一个全局方法convertLatLngToScreen
async function getScreenCoordinates(lat: number, lng: number) {
  const screenCoords = await browser.executeScript(`
    return window.convertLatLngToScreen(${lat}, ${lng});
  `);
  return { x: screenCoords.x, y: screenCoords.y };
}

拿到坐标后,直接把地图中心拖到这个坐标,或者直接点击。


二、点击对应经纬度的标记点

方案1:转屏幕坐标后直接点击(最直接)

和上面的方案3结合,拿到目标坐标的屏幕x/y后,直接用tap方法点击:

async function tapMarkerAtLatLng(lat: number, lng: number) {
  const { x, y } = await getScreenCoordinates(lat, lng); // 用上面的坐标转换方法
  await browser.tap({ x, y });
  await browser.pause(500); // 等待点击后的反馈
}

方案2:通过元素属性定位标记点(最稳定)

这是我最推荐的方案,只要让开发同学给每个充电标记点加唯一的可访问性标识,比如:

  • Android:给标记点的content-desc设置成charging-station-${lat}-${lng}
  • iOS:给标记点的accessibilityLabel设置成同样的内容

然后直接定位元素点击:

async function clickMarkerByLatLng(lat: number, lng: number) {
  // 拼接定位符,注意经纬度的精度(比如保留6位小数)
  const markerLocator = `~charging-station-${lat.toFixed(6)}-${lng.toFixed(6)}`;
  const marker = await $(markerLocator);
  await marker.waitForDisplayed({ timeout: 5000 });
  await marker.click();
}

这种方法的稳定性最高,不会因为地图缩放、屏幕尺寸变化而失效,强烈建议和开发同学沟通加这个标识。

方案3:通过元素属性筛选(适合无专属标识的情况)

如果开发不愿意加专属标识,也可以看标记点的其他属性,比如有些地图会把经纬度存在data-latdata-lng这类自定义属性里,或者标记点的文本包含坐标信息:

async function clickMarkerByAttributes(lat: number, lng: number) {
  // 替换成你App中标记点的实际属性
  const marker = await $(`//android.widget.ImageView[@data-lat="${lat}" and @data-lng="${lng}"]`);
  await marker.waitForDisplayed({ timeout: 5000 });
  await marker.click();
}

最后给你一套完整的流程示例

describe('Map E2E Test', () => {
  const TARGET_LAT = 39.908860;
  const TARGET_LNG = 116.397390;

  it('should navigate to marker and click it', async () => {
    // 1. 打开App到地图页面
    await browser.url('/map');
    await browser.pause(2000);

    // 2. 定位地图到目标坐标
    await setMapCenter(TARGET_LAT, TARGET_LNG); // 用上面的方法

    // 3. 点击标记点
    await clickMarkerByLatLng(TARGET_LAT, TARGET_LNG); // 用上面的方法

    // 4. 验证点击后的结果(比如弹出详情页)
    const detailPage = await $('//android.view.View[@content-desc="charging-station-detail"]');
    await expect(detailPage).toBeDisplayed();
  });
});

一些踩过的坑提醒

  • 权限问题:Android一定要在capabilities里设置autoGrantPermissions: true,或者在测试开始前手动允许位置、存储权限;iOS要在capabilities里加allowSimulatorLocationSimulation: true
  • 地图加载延迟:每次操作地图后一定要加pause或者waitFor,确保地图加载完成再执行下一步
  • 屏幕适配:不同尺寸的手机,坐标转换的结果会不一样,用元素定位的方法(方案2)可以避免这个问题
  • 缩放级别:点击前一定要把地图放大到足够级别,否则标记点可能会和其他元素重叠,导致点击失效

火山引擎 最新活动