{"id":13671155,"url":"https://github.com/dmoosocool/puppeteer-autotest","last_synced_at":"2025-08-25T08:07:48.019Z","repository":{"id":42168985,"uuid":"109354118","full_name":"dmoosocool/puppeteer-autotest","owner":"dmoosocool","description":"puppeteer autotest, 用puppeteer做页面自动化测试和restful接口测试.","archived":false,"fork":false,"pushed_at":"2024-06-18T15:18:42.000Z","size":81,"stargazers_count":45,"open_issues_count":1,"forks_count":10,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-08-23T10:44:27.947Z","etag":null,"topics":["autotest","puppeteer"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dmoosocool.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-11-03T05:02:14.000Z","updated_at":"2024-05-06T12:58:30.000Z","dependencies_parsed_at":"2024-11-11T08:43:37.195Z","dependency_job_id":null,"html_url":"https://github.com/dmoosocool/puppeteer-autotest","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dmoosocool/puppeteer-autotest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmoosocool%2Fpuppeteer-autotest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmoosocool%2Fpuppeteer-autotest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmoosocool%2Fpuppeteer-autotest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmoosocool%2Fpuppeteer-autotest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dmoosocool","download_url":"https://codeload.github.com/dmoosocool/puppeteer-autotest/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmoosocool%2Fpuppeteer-autotest/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272030128,"owners_count":24861457,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-25T02:00:12.092Z","response_time":1107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["autotest","puppeteer"],"created_at":"2024-08-02T09:01:00.983Z","updated_at":"2025-08-25T08:07:47.981Z","avatar_url":"https://github.com/dmoosocool.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"\n\n[TOC]\n\n# 介绍\n\n\u003e **Puppeteer**是一个通过[DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/)控制headless chromium的高级node库, 也可通过设置设置非headless Chromium.\n\u003e\n\u003e Puppeteer有chrome官方团队进行维护, 相对于其他如PhantomJs, CasperJs 前景更好.\n\n\n\n## Puppeteer 适合干些什么事?\n\n- 爬虫\n- 前端自动化测试（表单操作、事件模拟、键盘输入... 等）\n\n\n\n## 安装Puppeteer\n\n\u003e 建议使用新版本node.js (8+ 支持async/await 用法). \n\n```shell\nnpm i -S puppeteer //建议最好使用npm进行安装. \n```\n\n\n\n\u003e  顺利安装好会在 **./node_modules/puppeteer/.local-chromium** 中 若是不成功, 根据提示设置环境变量PUPPETEER_SKIP_CHROMIUM_DOWNLOAD,也可设置到npmrc中下载不包含chromium的 puppeteer. 自行下载chromium。\n\u003e\n\u003e  [手动下载地址](https://download-chromium.appspot.com/) (需翻墙….) 根据自己的系统选择对应的版本下载.\n\u003e\n\u003e  **注意：**\n\u003e\n\u003e  - **v64版本以下的chromium Puppeteer支持的不好**\n\u003e  - **若是手动下载的运行时在设置中需指定Chromium位置.**\n\u003e\n\u003e  ```javascript\n\u003e  const browser = await puppeteer.launch({\n\u003e   // 指定chromium路径 若是自己下载的需要指定下载路径.\n\u003e   executablePath: '/Applications/Chromium.app/Contents/MacOS/Chromium',\n\u003e   // true不会打开浏览器.\n\u003e   headless: false\n\u003e  });\n\u003e  ```\n\n## puppeteer-autotest\n\n\u003e 本来想用puppeteer + mocha + chai 直接写自动化测试的, 结果发现 mocha中执行puppeteer不能打开浏览器, 所以puppeteer-autotest 中添加了两个概念, **流程**和**步骤**。puppeteer-autotest, 在一个流程中可以队列执行步骤.\n\n### 流程\n\n\u003e 流程由多个步骤组成. \n\n#### 示例:\n\n```javascript\n// 正常流程.\nconst Tools = require('../../utils/tools');\nconst moment = require('moment');\nconst fs = require('fs');\nconst path = require('path');\n\n// 引入流程步骤.\nconst loginCnodejs = require('./steps/loginCnodejs');\nconst createTopic = require('./steps/createTopic');\nconst replyComment = require('./steps/replyComment');\n\n// 日志路径\nconst logPath = path.resolve(path.dirname(path.dirname(__dirname)) + path.sep + 'logs' + path.sep + moment().format('YYYYMMDDHHmmss'));\n// 若文件夹不存在创建日志文件夹.\nif (!fs.existsSync(logPath)) {\n    fs.mkdirSync(logPath);\n}\nprocess.env.logPath = logPath;\n\n// 流程名称\nconst procedureTitle = 'cnodejs 页面测试.';\n// 流程开始url.\nconst procedureBeginUrl = 'https://cnodejs.org/';\n\n// 流程队列\nlet step = [\n    loginCnodejs,\n    createTopic,\n    replyComment\n];\n\n// 从第一个步骤开始执行.\nlet index = 0;\n\nmodule.exports = async function () {\n    return new Promise((resolve, reject) =\u003e {\n        // 这不是一个restful的测试.\n        let isRestful = false;\n        // 开始一个流程\n        Tools.beginProcedure(procedureTitle, procedureBeginUrl, isRestful, (page, isRestful) =\u003e {\n            // 队列执行一个流程.\n            Tools.runStep(step, 0, procedureTitle, page, isRestful, () =\u003e {\n                item.stepCallback(page);\n            });\n            resolve();\n        });\n    });\n};\n\n```\n\n\n\n### 步骤\n\n\u003e 步骤应该保证一个步骤中只干一件事情(包括 **正常**及**异常** 步骤).\n\n####示例:\n\n```javascript\nconst Config = require('../../../config/config'); //引入配置项, 其中包含 browser和page.\nconst { timeout, log } = require('../../../utils/tools'); // 引入工具类.\n\n// 定义一个步骤. 登录Cnodejs.\nclass loginCnodejs {\n    // 设置步骤标题及步骤码.\n    static getConfig() {\n        // 设置步骤标题及步骤码.\n        return {\n            title: '登录 - cnodejs',\n            code: 1.1\n        }\n    }\n\n    // 步骤事件. (具体步骤干啥..)\n    static async stepCallback(page, next) {\n      \t// 执行loginCnodejs步骤.\n\n        // 执行下一个步骤.\n        next \u0026\u0026 next();\n    }\n};\n\nmodule.exports = loginCnodejs;\n```\n\n## Puppeteer常用命令\n\n- 设置浏览器.\n\n```javascript\nconst browser = await puppeteer.launch({\n  // 若是手动下载的chromium需要指定chromium地址, 默认引用地址为 /项目目录/node_modules/puppeteer/.local-chromium/\n  executablePath: '/Applications/Chromium.app/Contents/MacOS/Chromium',\n  timeout: 15000, //设置超时时间,\n  ignoreHTTPSErrors: true, // 如果是访问https页面 此属性会忽略https错误,\n  devtools: true, // 打开开发者工具, 当此值为true时, headless总为false,\n  headless: false, // 关闭headless模式, 不会打开浏览器,\n})\n```\n\n- 打开一个新标签页\n\n```javascript\nconst page = browser.newPage();\n```\n\n- 页面跳转\n\n```javascript\nawait page.goto('https://cnodejs.com'); //如果页面跳转其中一些资源加载超时会报错.\n\n// 建议这样写可避免因为promise所报的超时错误.\nawait page.goto('https://cnodejs.com', {timeout: 3000}).then( () =\u003e {\n    console.log('跳转成功并且资源正确加载完毕.');\n}, () =\u003e {\n    console.log('跳转成功, 资源加载超时.');\n});\n\n```\n\n\n\n- 设置浏览器参数,\n\n```javascript\nconst devices = require('puppeteer/DeviceDescriptors');\n// 设置测试机型.\nconst testDevice = devices['iPhone 6'];\nawait page.emulate(testDevice);\n```\n\n- 获取页面标题\n\n```javascript\nlet title = await page.title();\n```\n\n- 获取焦点\n\n```javascript\nawait page.focus('#elementId'); \n```\n\n- 点击按钮\n\n```javascript\nawait page.click('#elementId'); \nawait page.tap('#elementId'); //用于手机端\n```\n\n- 获取DOM\n\n```javascript\nlet el = await page.$('#elementId');  // 相当于document.querySelector('#elementId');\nawait el.click();\t// 执行点击事件\n\nlet list = await page.$$('.someclass'); // 相当于document.querySelectorAll('.someClass');\n```\n\n- 获取DOM属性\n\n```javascript\nlet inputValue = await page.$eval('#input', el =\u003e el.value);\n```\n\n- 文本输入\n\n```javascript\nawait page.type('#inputId', '输入内容.');\nawait page.type('#inputId', '输入内容.', { delay: 200 }); // 设置输入间隔200ms(拟人输入);\n```\n\n- evaluate\n\n```javascript\nlet result = await page.evaluate( () =\u003e {\n  // 获取一个元素, 这里可直接使用js\n  return document.getElementById('testEl').getAttribute('anyAttr');\n})\n\nconsole.log(result); // testEl的anyAttr属性值.\n```\n\n- waitFor 等待(元素或者函数或者一个延迟毫秒)\n\n\u003e [waitFor 详细文档](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#framewaitforselectororfunctionortimeout-options-args)\n\n```javascript\nawait page.waitFor(selectorOrFunctionOrTimeout[, options[, ...args]]);\n```\n\n- 设置页面样式\n\n```javascript\nawait page.mainFrame().addStyleTag({\n    content: '* { background-color: red; }';\n});\n```\n\n- 屏幕截图\n\n```javascript\nawait page.screenshot({\n  path: 'some/to/path.png',\n  fullPage: true // 全屏截取, 默认false.\n});\n```\n\n- 发送请求. 在浏览器中使用fetch发送请求.\n\n```javascript\n// 向http://example.com发送一个POST请求, 请求参数为 {a:1, b:2};\nlet result = await page.evaluete( async (options) =\u003e {\n   return await fetch('http://example.com', {\n        method: 'POST', // \n      \theader: {\n            'Content-Type': 'application/json; charset=utf-8'\n        },\n      \tbody: JSON.stringify(options)\n    })\n  \t\t.then(response =\u003e response.json())\n  \t\t.then(data =\u003e data)\n  \t\t.fail( e =\u003e console.log('Oops, error', e));\n}, { a: 1, b: 2});\nconsole.log(result); //接口返回值.\n\n```\n\n- 发送请求. 通过puppeteer的page.on('request'); 进行拦截. 使用goto进行触发请求.\n\n```javascript\nawait page.setRequestInterceptionEnabled(true);\npage.on('request', request =\u003e {\n  const overrides = {};\n  \n  // 如果是需要请求的地址.\n  if (request.url === 'http://www.google.com') {\n    //设置请求方式.\n    overrides.method = 'POST';\n    //设置参数\n    overrides.postData = 'a=b\u0026c=d';\n  }\n  request.continue(overrides);\n});\nlet response = await page.goto('http://www.google.com');\nresponse.json();// 将response.body 转成json。\nresponse.ok(); //  返回一个boolean值 如果状态码为200-299则为true, 其他则为false.\nresponse.status; // 返回状态码\nresponse.text(); // 返回 response body.\nresponse.headers // 返回 HTTP headers\n```\n\n- 关闭页面中的弹框\n\n```javascript\nconst puppeteer = require('puppeteer');\n\npuppeteer.launch().then(async browser =\u003e {\n  const page = await browser.newPage();\n\n  // 当页面中有弹框调起的时候触发.\n  page.on('dialog', async dialog =\u003e {\n    console.log(dialog.message()); //打印弹框的内容\n    await dialog.dismiss(); //关闭弹框\n  });\n  \n  page.evaluate(() =\u003e alert('1'));  // 浏览器中执行 alert('1');\n});\n```\n\n\n\n## 在做cnodejs自动化测试时遇到的问题\n\n\n\n1. 页面在跳转的时候经常资源加载超时,  同样也是获取一些用户头像时候网络超时.\n\n![页面跳转时经常资源加载超时](https://ws2.sinaimg.cn/large/006tKfTcgy1flbld370hij30mi0naaig.jpg)\n\n2. 在发布话题和回复话题中的编辑器…   \n\n![回复编辑器](https://ws3.sinaimg.cn/large/006tKfTcgy1flbm059iocj30ns060wfj.jpg)\n\n查看DOM结构这里的回复是表单提交 但是 将textarea.editor[name=\"r_content\"]中设置值依旧提醒回复内容不能为空... 有点绝望.\n\n到这里...... 通过页面的点击方法为cnodejs添加自动测试**失败**~\n\n还有 Mac版本的 chromium 不强行给页面所有元素设置字体 有情况会变成 框框...\n\n就算设置了也有可能有些位置会变成框框...\n\n有哪位老哥找到方法了告诉下...\n\n\n\n完成项\n\n- [x] 可以用户登录cnodejs\n\n- [ ] ~~创建话题~~  不能在编辑其中模拟输入内容. 失败.\n- [ ] ~~回复话题~~ 不能在编辑其中模拟输入内容. 失败.\n\n效果图\n\n![pagetest](https://ws3.sinaimg.cn/large/006tKfTcgy1flbwnk6skdg31a40qwe84.gif)\n\n\n\n## 通过puppeteer-autotest为cnodejs做页面自动化测试 发现几点问题.\n\n1. 发布话题的时候,  js校验只校验了板块选项卡, 而标题内容的校验都由服务端校验的. 这里的表单内容js全部校验一次 是不是可以缓解下服务端的压力?\n2. 同样的问题也出现在了回复话题中, 对于未填写回复内容的时候的校验也是由服务端校验的.\n\n\n\n## 下面来用puppeteer-autotest为cnodejs做restful api测试\n\n1. 在procedure 下新建文件夹restfulTest\n2. restfulTest中新建index.js 用来管理这个流程\n3. restfulTest中新建steps文件夹 该文件夹中存放所有的流程.\n\n\n\n完成项\n\n- 校验accessToken. checkAccessToken.\n- 获取话题 getTopic\n- 新建话题 postTopic\n- 修改话题 updateTopic\n\n#### 效果图\n\n![restful autotest](https://ws2.sinaimg.cn/large/006tKfTcgy1flbw5urrs0g30ew0lkgoy.gif)\n\n## 相关资料\n\n### Puppeteer案例\n\nhttps://juejin.im/entry/59ad6c4f5188250f4850dccc\n\nhttps://github.com/zhentaoo/puppeteer-deep\n\nhttps://segmentfault.com/a/1190000011627343\n\nhttp://www.cnblogs.com/dolphinX/p/7715268.html\n\n### 官方api\n\nhttps://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmoosocool%2Fpuppeteer-autotest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdmoosocool%2Fpuppeteer-autotest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmoosocool%2Fpuppeteer-autotest/lists"}