微信小程序哪些wifi+tcp+udp踩过的坑

这篇具有很好参考价值的文章主要介绍了微信小程序哪些wifi+tcp+udp踩过的坑。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、wifi操作流程

1、wx.startWifi 开启wifi模块

2、如果需要展示wifi列表则调用 wx.getWifiList(Object object)

注意:
请求获取 Wi-Fi 列表。wifiList 数据会在 onGetWifiList 注册的回调中返回。 Android 调用前需要 用户授权 scope.userLocation。

iOS 上将跳转到系统设置中的微信设置页,需要用户手动进入「无线局域网」设置页,并在系统扫描到设备后,小程序才能收到 onGetWifiList 回调。Android 不会跳转。

3、可以直接连接wifi wx.connectWifi

注意:
有可能wifi连接不上,需要传入forceNewApi 参数,文档中没有说明

wx.connectWifi({
      forceNewApi: true,
      SSID: "PUNKCYBER",
      password: "12345678910", //12345678910
      success(res3) {
       
      },
      fail(res) {
        console.log("wifi连接失败" + res.errCode + "  " + res.errMsg);
      },
    })
  },

android 手机连接wifi,连接成功后,会返回wifi信息,但是ios不会返回wifi信息。这个wifi信息有可能在连接tcp的时候会用到bssid,如果没有返回则可以调用 wx.getConnectedWifi

4、canvas保存为临时文件,ios 不显示
注意: backround-url 背景图片不显示 其实在image的组件中是显示的

5、TCP通讯
创建TCP : let tcp = wx.createTCPSocket();
监听绑定wifi事件 :tcp.onBindWifi
监听连接 : tcp.onConnect
监听消息 : tcp.onMessage
监听关闭 : tcp.onClose
监听错误 : tcp.onError
绑定wifi : tcp.bindWifi
连接tcp:tcp.connect
为什么从tcp转为udp:
connect能直接连接电脑端服务器tcp,但是连接硬件需要先绑定wifi,安卓没有问题,ios不支持bindWifi方法,ios一直连不上udp。所以后面从tcp转为了udp

6、UDP通讯
请忽略下面的tcp变量名,因为我是从tcp通讯改的udp通讯 UDP 有可能会限制包大小

创建UDP : let tcp = wx.createUDPSocket();
绑定

  if ("ios" == wx.getSystemInfoSync().platform) {
      this.globalData.tcp.bind(); // ios不需要端口
    } else {
      this.globalData.tcp.bind(20565); // android 需要端口
    }
  **监听方法事件** : tcp.onListening(();
 **监听报文的返回**: tcp.onMessage;
 **监听关闭**: tcp.onClose;
 **监听错误**: tcp.onError;
 发送: tcp.send({
  address: '192.168.4.1',
  port: 20565,
  setBroadcast: true, //ios 需要添加这个
  message: bufferArr[subTcpDataIndex]
})

7、wifi框架代码

// app.js
var packet = require('./utils/packet');
let wifiError = {
  "12005": "请打开wifi",
  "12006": "请打开GPS",
  "12007": "用户拒接连接wifi",
  "12010": "系统错误,请重试",
  "1505005": "请打开wifi或重启设备",
  "1505006": "请连接设备"
}


App({
  onLaunch() {
    console.log("onLaunch");
    // 展示本地存储能力
    wx.setEnableDebug({
      enableDebug: true
    })
    let tcp = wx.createUDPSocket();
    this.globalData.tcp = tcp;
    tcp.onListening((res) => {
      console.log("res==>", res);
      this.tcpConnectCallback();
    });

    tcp.onMessage((res) => {
      clearTimeout(getApp().globalData.timeoutTimer); //如果监听到有数据返回,在清除超时定时器
      let val = this.arrayBufferToHexString(res.message);
      console.log('onMessage-val', val)
      if (val == "4F4B0D0A") { //”OK\r\n”代表连接正常
        this.globalData.tcpDataIndex = this.globalData.tcpDataIndex + 1;
        packet.tcpWrite();
      } else if (val == "54494D45204F55540D0A") { //超时重新发送  
        //packet.tcpWrite();
        if (this.globalData.timeoutCount < 3) { //需要判断是分包发送还是整包发送
          this.globalData.timeoutCount++;
          packet.sendDataBySubPackage();
        } else {
          wx.hideLoading();
          wx.showToast({
            title: "更新失败,请重试",
            mask: true,
            icon: "none"
          })
        }
      } else if (val == packet.packageHex) { //分包发送完毕
        this.globalData.subTcpDataIndex = this.globalData.subTcpDataIndex + 1;
        packet.sendDataBySubPackage();
      } else if (val == packet.errorHex) {
        wx.hideLoading();
        wx.showToast({
          title: "更新失败,请重试",
          mask: true,
          icon: "none"
        })
      }
    })
    tcp.onClose((res) => {
      console.log('断开了', res)
      this.globalData.tcpIsClose = true
    })
    tcp.onError((res) => {
      console.log('tcp-错误了', res)
      // wx.hideLoading();
      //clearTimeout(this.globalData.timer);
      // errCode -2  Network is unreachable //设备断电了
      // errCode -2 bind socket fail:errno:48 errmsg:  

      // wx.showToast({ // 不提示错误信息
      //   title: res.errMsg,
      //   mask: true,
      //   icon: 'none',
      // })

      if (res.errMsg == "create sock fail udp alread exist") {
        wx.hideLoading();
        this.tcpConnectCallback();
      }
    })
  },
  onHide() {
    console.log("onHide")
    this.globalData.tcp.close();
  },
  tcpConnectCallback() {
    wx.hideLoading();
    clearTimeout(this.globalData.timer);
    this.globalData.tcpIsClose = false;
    console.log('tcp连接成功')
    packet.tcpWrite();
  },
  wifiInit() {
    let that = this;
    if ("ios" == wx.getSystemInfoSync().platform) {
      wx.showLoading({
        title: '连接中',
      })
    }
    wx.connectWifi({
      forceNewApi: true,
      SSID: "PUNKCYBER",
      password: "12345678910", //12345678910
      success(res3) {
        wx.hideLoading();
        console.log("连接wifi成功", res3)
        that.getConnectedWifi(); //ios手机会出现问题
        //that.connectTcp();
      },
      fail(res) {
        wx.hideLoading();
        wx.showToast({
          title: wifiError[res.errCode + ''] ? wifiError[res.errCode + ''] : res.errMsg,
          mask: true,
          icon: "none"
        })

        console.log("wifi连接失败" + res.errCode + "  " + res.errMsg);
      },
    })
  },
  connectTcp() {
    console.log('链接')
    wx.showLoading({
      title: "连接中",
      mask: true,
    })
    let timer = setTimeout(() => {
      if (this.globalData.tcpIsClose) {
        wx.showToast({
          title: '连接超时,请重试',
          mask: true,
          icon: 'none',
        })
      }
    }, 2000)
    this.globalData.timer = timer;
    this.globalData.tcpIsClose = true;
    if ("ios" == wx.getSystemInfoSync().platform) {
      this.globalData.tcp.bind(); // ios不需要端口
    } else {
      this.globalData.tcp.bind(20565); // android 需要端口
    }
  },
  tcpInit() {
    this.globalData.timeoutCount = 0;
    //判断wifi是否连接,wifi连接,则直接连接tcp,如果wifi未连接,则连接wifi然后再连接tcp
    let that = this;
    if (this.globalData.startWifi) {
      this.getConnectedWifi();
    } else {
      wx.startWifi({
        success(res) {
          console.log("初始化wifi模块成功" + res.errMsg)
          that.startWifi = true;
          that.getConnectedWifi();
        },
        fail(res) {
          wx.showToast({
            title: wifiError[res.errCode + ''] ? wifiError[res.errCode + ''] : res.errMsg,
            mask: true,
            icon: 'none'
          })
        }
      })
    }
  },
  getConnectedWifi() {
    let that = this;
    wx.getConnectedWifi({
      success(res) {
        console.log("获取WiFixinxi", res)
        if (!res.wifi || res.wifi.SSID != 'PUNKCYBER') {

          that.wifiInit();
        } else {
          that.connectTcp();
        }
      },
      fail(res) {
        wx.showToast({
          title: wifiError[res.errCode + ''] ? wifiError[res.errCode + ''] : (wifiError[res.errno + ''] ? wifiError[res.errno + ''] : res.errMsg),
          mask: true,
          icon: 'none'
        })
        console.log("获取wifi信息失败", res);
      }
    });
  },
  //buffer 转16进制
  arrayBufferToHexString: function (buffer) {
    const hexArr = Array.prototype.map.call(
      new Uint8Array(buffer),
      function (bit) {
        return ('00' + bit.toString(16)).slice(-2)
      }
    )
    return hexArr.join('').toUpperCase();
  },

  globalData: {
    bufferArr: [],
    tcpDataIndex: 0,
    subTcpDataIndex: 0,
    tcpDataArr: [],
    tcp: null,
    openid: "",
    deviceOnline: !1,
    deviceId: "",
    userImgList: {},
    userLikeList: [],
    tcpIsClose: true,
    imagesCount: 12,
    startWifi: false,
    startSendBefore: 0,
    ssid: '',
    timer: '',
    wifi: {},
    isUpdateFirstDate: true, //是否第一次校验时间
    timeoutCount: 0,
    timeoutTimer: 0,
  }
})

packet文章来源地址https://www.toymoban.com/news/detail-556013.html

let newLineHex = "0D0A"; //\r\n
let byte4Hex = "00000000"; //预留4字节0x00
let byte2Hex = "0000"; //预留2字节0x00
let testHex = "495053434c4f434b20544553540D0A";
let startSendImagesHex = "55504441544520504943545552450D0A";
let endDiyImagesHex = "5345542044495920454e440D0A";
let endBbdImagesHex = "5345542042424420454e440D0A";
let timeoutHex = "54494d45204f55540D0A"
let setTimeHex = "5345542054494D45"
let setLightHex = "53455420524742204C4544"
let packageHex = "44415441205345474D454E54204F4B0D0A"
let errorHex = "4552524F520D0A"

//16进制转字符串
const hexToStr = (hex, encoding) => {
  var trimedStr = hex.trim();
  var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
  var len = rawStr.length;

  var curCharCode;
  var resultStr = [];
  for (var i = 0; i < len; i = i + 2) {
    curCharCode = parseInt(rawStr.substr(i, 2), 16);
    resultStr.push(curCharCode);
  }
  var val = "";
  var arr = resultStr;
  for (let i = 0; i < arr.length; i++) {
    val += String.fromCharCode(arr[i]);
  }
  return val;
}

//字符串转16进制
const stringToHex = (str) => {
  var val = "";
  for (var i = 0; i < str.length; i++) {
    if (val == "") {
      val = str.charCodeAt(i).toString(16); //获取字符的Unicode码然后转16进制
    } else {
      val += str.charCodeAt(i).toString(16); //获取字符的Unicode码然后转16进制再拼接,中间用逗号隔开
    }
  }
  return val;
}
//十进制转十六进制
const tenToHex = (num, digit = 4) => {
  const hex = num.toString(16);
  return hex.padStart(digit, 0);
}

const firstTcpData = (sendDataArr) => {
  let globalData = getApp().globalData;
  globalData.tcpDataIndex = 0;
  // 全局存放tcp需要发送的数据组
  globalData.tcpDataArr = sendDataArr;
  globalData.startSendBefore = 0;

}
//tcp 写入数据
const tcpWrite = () => {

  let globalData = getApp().globalData;
  let isUpdateFirstDate = globalData.isUpdateFirstDate;
  if (isUpdateFirstDate && getApp().globalData.tcpDataArr.length != 1 && getApp().globalData.tcpDataArr[0].indexOf(setTimeHex) == -1) { //第一次要发送校验时间并且当前指令不是校验时间指令
    getApp().globalData.tcpDataArr.push(getNowTimePacket());
    getApp().globalData.isUpdateFirstDate = false;
  }
  let tcpDataArr = globalData.tcpDataArr;
  let tcpDataIndex = globalData.tcpDataIndex;
  // 将数据组遍历发送,过滤掉为空的数组
  if (tcpDataIndex < tcpDataArr.length) {
    // console.log(`发送${tcpDataIndex}次`)
    let content = `正在更新${tcpDataIndex+1- globalData.startSendBefore}` + "/" + globalData.imagesCount;
    let tcpData = tcpDataArr[tcpDataIndex];
    if (tcpData) {
      if (tcpData == testHex) {
        content = "正在测试连接";
        globalData.startSendBefore++;
      } else if (tcpData == startSendImagesHex) {
        content = "准备更新图片";
        globalData.startSendBefore++;
      } else if (tcpData == endDiyImagesHex || tcpData == endBbdImagesHex) {
        content = "更新图片完毕";
      } else if (tcpData.indexOf(setTimeHex) != -1) {
        content = "正在同步时间";
      } else if (tcpData.indexOf(setLightHex) != -1) {
        content = "正在同步灯光";
      }
      console.log(content)
      // console.log("发送的报文",tcpDataArr[tcpDataIndex]);
      wx.showLoading({
        title: content,
       // mask: true,
      })
      getApp().globalData.subTcpDataIndex = 0;
      getApp().globalData.bufferArr = getBufferArrayBy1000(tcpDataArr[tcpDataIndex]);
      sendDataBySubPackage();

    } else {
      getApp().globalData.tcpDataIndex = tcpDataIndex + 1;
      tcpWrite();
    }

  } else {
    wx.showToast({
      title: '更新成功',
      mask: true,
      icon: 'success',
    })
    getApp().globalData.tcp.close(); //tcp 断开,小程序无法再次连接tcp
  }
}

const sendDataBySubPackage = () => {
  let globalData = getApp().globalData;
  let tcp = globalData.tcp;
  let subTcpDataIndex = globalData.subTcpDataIndex;
  let bufferArr = globalData.bufferArr;
  if (subTcpDataIndex < bufferArr.length) {
    tcp.send({
      address: '192.168.4.1',
      port: 20565,
      setBroadcast: true, //ios 需要添加这个
      message: bufferArr[subTcpDataIndex]
    })
    //1s未回复,定义为超时
    let timer = setTimeout(()=>{
        if(getApp().globalData.timeoutCount<3){ //需要判断是分包发送还是整包发送
          console.log("响应超时",getApp().globalData.timeoutCount);
          getApp().globalData.timeoutCount = getApp().globalData.timeoutCount+1;
          sendDataBySubPackage();
        }else{
          wx.hideLoading();
          wx.showToast({
            title: "更新失败,请重试",
            mask: true,
            icon:"none"
          })
        }
    },3000)
    getApp().globalData.timeoutTimer = timer;
    console.log("我发送了数据",subTcpDataIndex,bufferArr.length)
  }
}

const getBufferArrayBy1000 = (data) => {
  let num = 0;
  let len = 1000;
  if (typeof data == "undefined") return [];
  let allBuffer = hexStringToArrayBuffer(data);
  let bufferLen = allBuffer.byteLength;
  let bufferArray = [];
  while (bufferLen > 0) {
    let buffer;
    if (bufferLen > len) {
      buffer = allBuffer.slice(num, num + len);
      num = num + len;
      bufferLen -= len;
      bufferArray.push(buffer);
    } else {
      buffer = allBuffer.slice(num, num + bufferLen);
      num += bufferLen;
      bufferLen -= bufferLen;
      bufferArray.push(buffer);
    }
  }
  return bufferArray;
}
const hexStringToArrayBuffer = (str) => {
  //十六进制转ArrayBuffer
  return new Uint8Array(str.match(/[\da-f]{2}/gi).map(function (h) {
    return parseInt(h, 16)
  })).buffer
}


//mode= "DIY" 表盘模式 mode= "BBD" 表白模式
// no: 图片索引 00 - 99 月:10,日11
const getImagePacket = (filePath, no, mode = 'DIY') => {
  const fs = wx.getFileSystemManager()
  // 同步接口
  try {
    const fileDataHex = fs.readFileSync(filePath, 'hex', 0)
    // ”SET DIY_00.jpg\r\n”+预留4字节0x00+2字节0x00+2字节图片大小+图片数据+”\r\n” 表盘模式
    let fileSizeHex = tenToHex(parseInt(fileDataHex.length / 2));
    let start = `SET ${mode}_${no}.jpg`;
    let startHex = stringToHex(start);
    let sendDataHex = (startHex + newLineHex + byte4Hex + byte2Hex + fileSizeHex + fileDataHex + newLineHex).toUpperCase();
    // console.log("发送的图片数据报文", sendDataHex)
    return sendDataHex;
  } catch (e) {
    console.error(e)
  }
}

//mode= "DIY" 表盘模式 mode= "BBD" 表白模式
// no: 图片索引 00 - 99 月:10,日11
const getImagePacketByHttpUrl = (filePath, no, mode = 'DIY') => {
  // 同步接口
  return new Promise((resolve, reject) => {
    wx.request({
      url: filePath, //获取图片的URL
      method: "get",
      responseType: 'arraybuffer', //ArrayBuffer涉及面比较广,我的理解是ArrayBuffer代表内存之中的一段二进制数据,一旦生成不能再改。可以通过视图(TypedArray和DataView)进行操作。
      success: (res) => {
        const fileDataHex = arrayBufferToHexString(res.data);
        // ”SET DIY_00.jpg\r\n”+预留4字节0x00+2字节0x00+2字节图片大小+图片数据+”\r\n” 表盘模式
        let fileSizeHex = tenToHex(parseInt(fileDataHex.length / 2));
        let start = `SET ${mode}_${no}.jpg`;
        let startHex = stringToHex(start);
        let sendDataHex = (startHex + newLineHex + byte4Hex + byte2Hex + fileSizeHex + fileDataHex + newLineHex).toUpperCase();
        // console.log("发送的图片数据报文", sendDataHex)
        resolve(sendDataHex)
        //return sendDataHex;
      },
      fail(res) {
        console.log("失败", res);
      }
    })


  })

}
const arrayBufferToHexString = (buffer) => {
  const hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ('00' + bit.toString(16)).slice(-2)
    }
  )
  return hexArr.join('').toUpperCase();
}
//同步时间报文
const getNowTimePacket = () => {
  let date = new Date();
  let fullYear = date.getFullYear() + '';
  const year = tenToHex(parseInt(fullYear.substring(fullYear.length - 2)), 2);
  const month = tenToHex(date.getMonth() + 1, 2);
  const day = tenToHex(date.getDate(), 2);
  const hour = tenToHex(date.getHours(), 2);
  const minute = tenToHex(date.getMinutes(), 2);
  const second = tenToHex(date.getSeconds(), 2);

  let start = `SET TIME`;
  let startHex = stringToHex(start);
  let dateTimeHex = year + month + day + hour + minute + second;
  let sendDataHex = (startHex + newLineHex + byte4Hex + dateTimeHex + byte4Hex + newLineHex).toUpperCase();
  //console.log("发送的时间数据报文", sendDataHex)
  return sendDataHex;
}

//灯光报文
const getRGBPacket = (onOffStatus, bright, sleepStatus, lightMode, GRB) => {
  console.log("原始数据");
  console.log(onOffStatus, bright, sleepStatus, lightMode, GRB);
  let start = `SET RGB LED`;
  let startHex = stringToHex(start);
  let onOffStatusHex = onOffStatus ? "01" : "00";
  let brightHex = tenToHex(bright, 2);
  let sleepStatusHex = sleepStatus ? "01" : "00";;
  let lightModeHex = lightMode.toString().padStart(2, 0);
  let GRBHex = GRB.substring(1);
  console.log("16进制数据");
  console.log(onOffStatusHex, brightHex, sleepStatusHex, lightModeHex, GRBHex);
  let sendDataHex = (startHex + newLineHex + byte4Hex + onOffStatusHex + brightHex + sleepStatusHex + lightModeHex + GRBHex + byte4Hex + newLineHex).toUpperCase();
  console.log("发送的RGB数据报文", sendDataHex)
  return sendDataHex;
}

module.exports = {
  getImagePacket,
  getNowTimePacket,
  getRGBPacket,
  tcpWrite,
  hexStringToArrayBuffer,
  testHex,
  firstTcpData,
  startSendImagesHex,
  endDiyImagesHex,
  endBbdImagesHex,
  timeoutHex,
  packageHex,
  sendDataBySubPackage,
  errorHex,
  getImagePacketByHttpUrl
}

到了这里,关于微信小程序哪些wifi+tcp+udp踩过的坑的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 扫码跳转小程序终极方案,详细记录踩过的坑!不信进来看!扫描普通二维码进入小程序功能记录(两种方式)

    小程序管理平台 :https://mp.weixin.qq.com/ 选择 :开发管理-开发设置-扫普通链接二维码打开小程序 校验文件 点击添加进入配置页面 !!!还有一个校验文件,这个必须扔到服务器上面,放在域名下根目录即可,只要在二维码规则下的地址可以访问到即可 放在域名下根目录即可

    2024年02月13日
    浏览(52)
  • Spark搭建日志,记录一些踩过的坑

    本人在Centos中使用三个虚拟机(node1,node2,node3)搭建hadoop与Spark分布式环境(具体见后记中的Hadoop安装),本文记录一些踩过的坑 解决办法:sudo chown -R 用户名 /spark(spark或者hadoop所在目录) 原理:文件的初始所有者不是用户名(如root),要把spark目录的初始所有者更换为自

    2024年03月14日
    浏览(86)
  • docker+selenium+firefox | 我踩过的坑

    为了实现SSPUBot不在我电脑上部署,我只能将其制成Docker。 要知道SSPUBot在开发的时候用了selenium+Firefox的想法开发,所以Docker里面必须要有Firefox,结果这就让见识到了最顽固的错误 selenium.common.exceptions.WebDriverException: Message: Process unexpectedly closed with status 255 我们还是省略我找的

    2024年01月22日
    浏览(56)
  • 关于python的mediapipe库踩过的坑

      大家好,我是csdn的博主: lqj_本人 这是我的个人博客主页: lqj_本人的博客_CSDN博客-微信小程序,前端,vue领域博主 lqj_本人擅长微信小程序,前端,vue,等方面的知识 https://blog.csdn.net/lbcyllqj?spm=1000.2115.3001.5343 哔哩哔哩欢迎关注: 小淼前端 小淼前端的个人空间_哔哩哔哩_bilibil

    2024年01月17日
    浏览(39)
  • 一卡通水控电控开发踩过的坑

    最近在做一个项目,是对接一卡通设备的。我一开始只拿到设备和3个文档开局。不知道从哪下手。一步一步踩坑过来。踩了很多没有必要的坑,写出来给有用的人吧。 有个读卡器,一开始什么软件也不提供。我都不知道是干嘛用的。后来问客服才知道有一个测试软件。我真

    2024年01月23日
    浏览(62)
  • hql(hive sql)中的join及踩过的坑

    1 几种join方式 join join 对应于 inner join 内连接。 当多张表进行 join 的时候,所有表中与 on 条件中匹配的数据才会显示。 hql (即 hive sql )的 on 子句中只支持 and ,不支持 or ,也不支持 null 的对比。 left outer join 左外连接,也称为左连接。 以左表为基准,如果右表有条件匹配

    2024年01月21日
    浏览(44)
  • 「AntV」X6开发实践:踩过的坑与解决方案

    长期更新版文档请移步语雀(「AntV」X6开发实践:踩过的坑与解决方案 (yuque.com)) --Recent update:2024-01-05 相信你们在开发中更多的需求是需要自定义拖拽源,毕竟自定义的功能扩展性高一些,而且可以根据你的业务需求灵活设置。自定义拖拽的优点就是:万物皆可成为拖拽源,

    2024年02月08日
    浏览(105)
  • 嵌入式-stm32重要基础知识(及踩过的坑)

    1、固件库: 固件库就是函数的集合,固件库函数的作用是向下负责与寄存器直接打交道, 向上提供用户函数调用的接口(API)。 2、CMSIS标准与固件库的关系 就是对固件库函数的要求。 ARM 公司为了能让不同的芯片公司生产的 Cortex-M3 芯片能在软件上基本兼容,和芯片生产商

    2024年02月04日
    浏览(61)
  • 真人踩过的坑,告诉你避免自动化测试常犯的10个错误

    虽然从自己的错误中学习也不错,但从别人的错误中学习总是更好的。 作为一个自动化测试人员,分享常见的容易犯的10个错误,可以从中吸取教训,引以为鉴。 一、必要时才自动化 新人小王接到为Web应用程序自动化测试脚本的任务时,既高兴又紧张,因为这是他进入团队

    2023年04月08日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包