# auto-test **Repository Path**: eightFlying/auto-test ## Basic Information - **Project Name**: auto-test - **Description**: 前端自动化测试(单元测试、端对端测试) - **Primary Language**: JavaScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-08-31 - **Last Updated**: 2020-12-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # auto-test > vue中可以自动配置:单元测试 unit test 与端对端测试 e2e test ## 持续集成 - 频繁地(一天多次)将代码集成到主干 能够快速发现错误、防止分支大幅偏离主干 - 代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成 ## 单元测试 unit test ### 概念名词 - Karma 一个测试运行器,它运行一个Web服务器,其中包含项目的应用程序代码,并对其执行测试 - Mocha JavaScript的测试框架 - Chai 可以与Mocha一起使用的断言库 ### Karma - 配置文件karma.conf.js里面默认配置了很多插件的内容,基本上不需要调整 ### Mocha #### 两个重点api - describe(name, fn) 定义一组测试 可以在一组测试里面再定义一组测试 name:这一组测试的描述 通常是文件名 - describe.only(name, fn) 只测试其中某一组测试 - describe.skip(name, fn) 跳过某一组测试 - it(name, fn) 定义一项测试 name:对这一项测试的描述 - hook 钩子函数 - before、after、beforeEach、afterEach ### Chai #### 两种BDD风格 expect和should - expect 的引入仅需要引入 expect 函数,而 should 的引入需要引入 should 的函数执行 - should 不适用于 IE 而且在一些情况下他将可能不会工作 #### 链式语言结构 仅提高可读性 无实际作用 - to、be、been、is、that、which、and、has、have、with、at、of、same、but、does、still #### 真正的断言接口 - .not 否定在其之后链接的所有断言。 - .true/.false 断言目标是否为true或false - .equal 相等或不相等 - .null/.undefined 断言目标是否为null/undefined - .NaN 断言目标值不是数值 - .empty 断言空值 - .exist 断言目标既不是null也不是undefined - .within 断言目标值在某个区间范围内,可以与length连用 - .instanceof 断言目标是某个构造器产生的实例 - .property(name, [value]) 断言目标有以name为key的属性 - .deep 将.equal, .include, .contain, .members, .keys 和 .property放在.deep链式之后将导致使用深度相等的方式来代替严格相等 - .nested 在其后使用的.property 和 .include断言中可以使用.和括号表示法 如果. 或者 []是属性名的一部分,可以在它们之前添加双反斜杠进行转义 .nested不可与.own断言连用 - .own 使得其后的.property 和 .include断言中的继承属性被忽略 - .ordered 使得其后的.members断言需求以相同的顺序断言其成员 当共同使用.include和.orderd时,排序开始于数组的首部 - .any 使得跟在其后的.key断言仅需求目标包含至少一个所给定的键名,它与需求目标满足所有所给键的.all断言是相反的 - .all 使得跟在其后的.key断言仅需求目标需要包含所有所给的键名 - .lengthOf(n[, msg]) 断言目标的length或size与给定值相同,接受参数msg在断言错误时给出提示 - .match(re[, msg]) 断言目标与给定的正则规则相匹配 - .string(str[, msg]) 断言目标字符串包含所给子串,支持message在出错时给出用户信息 - .keys(key1[, key2[, …]]) 断言目标对象、数组、map集、set集包含所给键,只有目标的自身属性在所搜索范围内 - .respondTo(method[, msg]) 当目标是一个非函数对象时, .respondTo断言该对象包含所提供方法名称的方法,该方法可以是自身的也可以是继承的,可以是可枚举也可以时不可枚举的。当目标是一个函数时断言该函数原型属性又一个与所给名称相同的方法。同样的,该方法可以是自身的也可以是继承的,可以是可枚举也可以时不可枚举的。 - .closeTo(expected, delta[, msg]) 断言目标值是一个基于期待值(expected)+/- 差值(delta)范围内的数字 - .members(set[, msg]) 断言目标数组与所给数组set具有相同成员 - .oneOf(list[, msg]) 断言目标时期待数组list的成员 - .change(subject[, prop[, msg]]) 断言给定函数subject在目标函数之前调用和在目标函数之后调用的返回值不同 - .increase(subject[, prop[, msg]]) 断言给定函数subject在目标函数之后调用比在目标函数之前调用的返回值更大 - .decrease(subject[, prop[, msg]]) 断言给定函数subject在目标函数之后调用比在目标函数之前调用的返回值更小 - .by(delta[, msg]) 跟在上面三个后面断言他们的差量、增量、减少量为给定的差值 - .extensible 断言目标是可扩展的,这意味着可以向其添加新属性。原始值是绝对不可扩展的 - .sealed 断言目标是密封的,这意味着将无法加入新属性,并且已存在的属性无法重新配置或者删除,这也意味着已存在的属性在重新分配不同值之后仍然可能保持。原始值均是密封的。 - .frozen 断言目标是密封的,这意味着将无法加入新属性,并且已存在的属性无法被重新分配值,重新配置或者删除。原始值总是冻结的。 - .finite 断言目标是一个非NaN的数字,且该数字既不是正无穷也是负无穷。 - .fail([message]) 抛出一个错误 - .fail(actual, expected, [message], [operator]) 分别 传入实际值,期待的值和错误提示,并将这个错误抛出。 ## 端对端测试 e2e test ### 工程结构 - custom-assertions // 自定义断言 - reports // 输出报表文件夹 - nightwatch.conf.js // nightwatch 运行配置 - runner.js // 运行器 - specs // 测试文件 ### 运行 npm run e2e 报错 ``` Error retrieving a new session from the selenium server Connection refused! Is selenium server started? ``` #### 卸载 vue-cli 自动安装的 chromedriver 然后自己重新安装 `npm i chromedriver -D` ### Nightwatch的API > 来自 https://www.jianshu.com/p/936bee074b66 #### Expect 无实际意义的修饰 - to、be、been、is、that、which、and、has、with、at、of、does - 时间 .before(ms)(表示一段时间之前)、.after(ms)(表示一段时间之后) #### Assert 断言 > 以.assert/.verify开头的两套相同的方法库,区别是assert如果断言失败则退出整个测试用例所有步,verify则打印后继续进行。 ```javascript .attributeContains(selector, attribute, expected[, message]) //检查指定元素(selector)的指定属性(attribute)是否包含有期待的值(expected)打印出指定信息(可选填的message)其他方法讲解类似,不一一赘述 .attributeEquals(selector, attribute, expected[, message]) //检查元素指定属性是否等于预期 .containText(selector, expectedText[, message]) //包含有指定的文本 .cssClassPresent(selector, className[, message]) //检查元素指定class是否存在 .cssClassNotPresent(selector, className[, message]) //检查元素指定class是否不存在 .cssProperty(selector, cssProperty, expected[, message]) //检查元素指定css属性的值是否等于预期 .elementPresent(selector[, message) //检查指定元素是否存在于DOM中 .elementNotPresent(selector[, message) //检查指定元素是否不存在于DOM中 .hidden(selector[, message) //检查指定元素是否不可见 .title(expected[, message]) //检查页面标题是否等于预期 .urlContains(expectedText[, message]) //检查当前URL是否包含预期的值 .urlEquals(expected[, message]) //检查当前URL是否等于预期的值 .value(selector, expectedText[, message]) //检查指定元素的value是否等于预期 .valueContains(selector, expectedText[, message]) //检查指定元素的value是否包含预期的值 .visible(selector[, message) //检查指定元素是否可见 ``` #### Commands 指令 可以操作DOM BOM对象 ```javascript .clearValue(selector[, message]) //清空input、textarea的值 .click(selector[, callback]) //callback为执行完命令后需要执行的回调 .closeWindow([callback]) .deleteCookie(cookieName[, callback]) .deleteCookies([callback]) .end([callback]) //结束会话(关闭窗口) .getAttribute(selector, attribute, callback) .getCookie(cookieName, callback) .getCookies(callback) .getCssProperty(selector, cssProperty, callback) .getElementSize(selector, callback) .getLocation(selector, callback) .getLocationInView(selector, callback) .getLog(typeString, callback) //获取selenium的log,其中type为string或者function .getLogTypes(callback) .getTagName(selector, callback) .getText(selector, callback) .getTitle(callback) .getValue(selector, callback) .init([url]) //url方法的别名,如果不传url则跳转到配置中的launch_url .injectScript(scriptUrl[, id, callback]) //注入script .isLogAvailable(typeString, callback) //typeString为string或者function,用来测试log的type是否可用 .isVisible(selector, callback) .maximizeWindow([callback]) //最大化当前窗口 .moveToElement(selector, xoffset, yoffset[, callback]) //移动鼠标到相对于指定元素的指定位置 .pause(ms[, callback]) //暂停指定的时间,如果没有时间,则无限暂停 .perform(callback) //一个简单的命令,允许在回调中访问api .resizeWindow(width, height[, callback]) //调整窗口的尺寸 .saveScreenshot(fileName, callback) .setCookie(cookie[, callback]) .setValue(selector, inputValue[, callback]) .setWindowPosition(offsetX, offsetY[, callback]) .submitForm(selector[, callback]) .switchWindow(handleOrName[, callback]) .urlHash(hash) .useCss() //设置当前选择器模式为CSS .useXpath() //设置当前选择器模式为Xpath .waitForElementNotPresent(selector, time[, abortOnFailure, callback, message]) //指定元素指定时间内是否不存在 .waitForElementNotVisible(selector, time[, abortOnFailure, callback, message]) //指定元素指定时间内是否不可见 .waitForElementPresent(selector, time[, abortOnFailure, callback, message]) .waitForElementVisible(selector, time[, abortOnFailure, callback, message]) ``` #### webdriver protocol 操作更底层的东西 - Sessions、Navigation、Command Contexts、Elements、Element StateElement Interaction、Element Location、Document Handling、Cookies、User Actions、User Prompts、Screen Capture、Mobile Related