foxlele2014 / boring

boring
0 stars 0 forks source link

自动化测试 #23

Open foxlele2014 opened 7 years ago

foxlele2014 commented 7 years ago

记录收集到的资料。

foxlele2014 commented 7 years ago

jest-enzyme-react

foxlele2014 commented 7 years ago

jest-enzyme

foxlele2014 commented 7 years ago

jest

foxlele2014 commented 7 years ago

enzyme

foxlele2014 commented 6 years ago

最近说是要写前端的自动化测试。。 应该是属于业务类的自动化测试。

然后就有点疑问?哪些该写哪些不用写? 因为大部分是显而易见的界面展示类的,没有和后端的交互逻辑的(如输入,验证、发送之类的),感觉这类才需要写。 毕竟是业务类的。不是通用组件类的。

所以就打算参考下qa方面写的测试用例。

-------------------更-----------------

实际到写起来的时候才发现不容易啊不容易= =。实际上并不是如实际上的所见即所得,而是有很多种见的方式,然后得的时候也会有点茫然= =。

foxlele2014 commented 6 years ago

shallow,render,mount如何选择

foxlele2014 commented 6 years ago

引入view组件页面的时候,因为在webpack里定义了alias,如@utils/fetch,然后jest读取的时候就无法定位到该模块。

这时就修改package.json修改jest的配置,moduleNameMapper, 增加类似"^@utils(.*)$": "/resources/assets/utils/$1" 这样的配置,

就可以了

--------更·-------------- 但是似乎这个moduleNameMapper,是表示需要mock的内容 = =。

突然不太懂了窝~

foxlele2014 commented 6 years ago

问题2:在模板里写了一个加密用的字符串。 然后在对应需要用的到view.js里对这个字符串进行了获取, document.getElementsById('xx').value 可能因为无法获取到这个xx,所以执行yarn jest的时候,就一直提示Cannot read property 'value' of null

对应的我也在jest的setup.js文件里加上了构建对应的xx,但是还是一直读取不到。

好神奇的是打印这个虚拟的dom环境,居然只有一个子节点。好神奇啊。 明明放了两个children

------------------- 分割线-------------------- 不太懂。用jsDom创建的没有赋值到当前的环境下。 jest默认是使用jsdom的环境的。

然后解决办法是: 在setup.js里打印了document,发现是存在的, if(typeof document === 'undefined') {使用jsdom创建}else{ document.body.innerHTML='xxx'}

这样在引用的时候就能获取到xxx里的内容了。。。

实在不懂为什么,明明按照jsdom里的操作,给global.window,document都赋值了,依旧里边的都还是空的。没有覆盖掉吗?

foxlele2014 commented 6 years ago

真特么恶心。= =.感觉找个元素得找你半天= =。

foxlele2014 commented 6 years ago

一些坑和一些API的使用方法注意点: 首先是enzyme的三个渲染api的区别

shallow、mount、render

foxlele2014 commented 6 years ago

shallow、mount的渲染都得基于jsdom环境。

然后测试modal内部的时候就坑爹了。modal是在body里的。不在jsdom里边= =。 这时你就找不到了。。。 据说要使用react本身的原生测试方法。 具体请看: https://reactjs.org/docs/test-utils.html

foxlele2014 commented 6 years ago

shallow渲染仅仅基于目前你在测试文件里能看见的元素

所以当模拟方法的时候可以使用测试文件里定义的各种事件。如onSearch

但是mount渲染出来的是reactWrapper,模拟事件的时候就已经不是search方法了,而是必须是react里存在的。且是这个组件最终具体到某个元素的实际方法。

foxlele2014 commented 6 years ago

当某个mock的方法被使用了之后,就会再mock.calls里找到对应的痕迹 mock.calls:[[{"limit": 3, "name": "", "page": 1, "role_id": ""}]] 实际上是调用这个函数的各种参数。。 假如下一个test又想测试某个按钮点击的时候,这个函数是否调用的,就需要mockfn.mockclear()

        //Resets all information stored in the mockFn.mock.calls and mockFn.mock.instances arrays.
        //不使用mockFn.mock.calls或者mockFn.mock.instances需要执行mockClear吗?
        //toBeCalled是如何判断的??是去mockFn.mock.calls里取值吗?
        //经过测试,应该就是直接去calls里对比了。
foxlele2014 commented 6 years ago

// jest会自动mock所有的依赖模块,对模块中所有的输出方法予以遍历并进行mock,对于要测试的模块使用jest.dontMock标识,jest就不会去mock.

或者这样 jest.disableAutomock();

/**
 * 将原目录下的services.js替代了。。。怎么替代的???= =。
 * 当在view里dispatch effects,yield call对应的请求时怎么替换的= =。
 * https://github.com/kentcdodds/how-jest-mocking-works
 * jest.mock(moduleName, factory, options)
 * Jest will automatically hoist jest.mock calls to the top of the module (before any imports)
 * When a manual mock exists for a given module, Jest's module system will use that module when explicitly calling jest.mock('moduleName'). However, manual mocks will take precedence over node modules even if jest.mock('moduleName') is not called. To opt out of this behavior you will need to explicitly call jest.unmock('moduleName') in tests that should use the actual module implementation.
 * "jest.mock" changes the behavior of the node "require" function to use the mock, it doesn't do a require itself.
 */
jest.mock('../services', () => require('../_mocks_/services'));
foxlele2014 commented 6 years ago

mock之后的函数

/**
         * getUserList:
         { [Function: mockConstructor]
           _isMockFunction: true,
           getMockImplementation: [Function],
           mock: [Getter/Setter],
           mockClear: [Function],
           mockReset: [Function],
           mockReturnValueOnce: [Function],
           mockReturnValue: [Function],
           mockImplementationOnce: [Function],
           mockImplementation: [Function],
           mockReturnThis: [Function],
           mockName: [Function],
           getMockName: [Function],
           mockRestore: [Function] }
         }
         */
foxlele2014 commented 6 years ago

一个test suites里的测试都会共用同一个环境。

//前一个test的结果会影响后一个test吗,执行test时它的环境会重置吗? //如点击了某个弹窗,之后下一个test,他是点击另一个,这时前一个的弹窗还会在吗? //应该还会在 //beforAll是表示在每个test执行之前会执行的吗? //只执行一次,在test执行之前。beforeEach是在每个test之前都会执行一遍

foxlele2014 commented 6 years ago
 beforeAll(() => {
        app = dva();
        app.model(model);
        app.router(() => {})
        app.start();
        //替代connect传入
        wrapper = mount(<Account />
})

假如一个测试环境里重复使用了两次model,就会有warning提示。是react的提示= =。

因为很坑的,我在一个测试文件里写了两个describe,是两种渲染方式,但是用dav重复初始化了同一个组件。。。。

foxlele2014 commented 6 years ago

在写某些弹窗的测试的时候,因为我的弹窗的各种东西都来自父亲,然后我就不知道要怎么测试父亲传给我的各种函数了。(怎么测回到父亲身上。。。)。感觉我只能在父亲身上测试了。

这时就体会到了。属于这个弹窗自己的就他自己写好了。不要用父亲传给他了。好烦啊。。。

因为我要测试这个弹窗的各种表单(需要判断一个错误输入时,他是否会提示(即不执行某个请求的操作)。

foxlele2014 commented 6 years ago

恩。现在基本知道了流程。。。然后打算再把jest和enzyme的文档看一遍。。。。

foxlele2014 commented 6 years ago

全栈测试实战:用Jest测试Vue+Koa全栈应用

有个可以在编辑器debug代码的还不错。