Начало работы с тестовым артефактом ММ Кипарис

внешний интерфейс JavaScript Webpack тестовое задание

не так давно

Говорят, что в компании каждый день два фронтенда и баги, почему? Винить только тест MM Qingrenguo, у брата Qingyu есть ошибка. ✧(๑•̀ㅂ•́)و✧ Но в последнее время эти двое немного волновались Σ(っ °Д °;)っ. Тестовый ММ несколько раз выдавал экстренные ошибки, и им предлагается исправить ошибку, однако воспроизвести ошибку онлайн сложно, и после исправления обнаруживается, что она не была исправлена. Как это сделать?

Front-end Jun 666 обнаружен однаждыE2Eтестовый артефактcypressПосле этого я тайно практиковал фокусы и фиксил баги, чтобы становиться все больше и больше 6. Тестовый ММ улыбался и говорил ему каждый день, 666, тебе действительно 6, ММ это так нравится (๑•́ ₃ •̀๑) Другой фронтенд джентльмен, 555, каждый день сталкивается с накоплением Бага как гора, а тестовый ММ его игнорирует после упоминания нового бага≡ ̄﹏ ̄≡

как погоня代码永无bug, кстати есть идеальный фронтенд (ง •̀_•́)ง для общения с тестовым ММ продуктом, думаю надо научиться им пользоватьсяcypressвыполнятьE2Eтестирование для улучшения качества кода. Итак, давайте посмотрим, как начатьcypressтестовая структура.

кипарис три вопроса - кто ты

cypressвmochaНабор готовых API, созданных поверхE2EПлатформа тестирования, по сравнению с другими средами тестирования, предоставляет набор собственных лучших практик, не требует других библиотек инструментов тестирования, проста в настройке, но чрезвычайно мощна, вы можете использоватьwebpackКонфигурация проекта также обеспечивает мощныйGUIграфические инструменты. Легко начать, легко начать, как освоиться (。→‿←。)

cypressВ тесте режима графического интерфейса используется настоящий браузер, а режим без графического интерфейса используетсяchrome-headless, вместо того, чтобы тестировать симулированным способом, он более реалистично показывает процесс тестирования и результаты в реальной среде.

кипарис три вопроса - в чем ваши преимущества

Cypress обладает рядом мощных функций:

  • Поставляется с инструментами графического интерфейса, вы можете щелкнуть все, что хотите протестировать, вы также можете просмотреть весь процесс тестирования и, если хотите, можете записать экран (запись экрана можно отправить на тест MM, чтобы увидеть, убедитесь, что она говорит что мой брат действительно хороший. Я не рассказываю ему об обычных людях. ๑乛◡乛๑)
  • Каждый шаг теста имеет снимок, вы можете просматривать статус страницы каждого процесса с помощью инструментов графического интерфейса, а не снимок экрана, а реальную среду DOM страницы!
  • Благодаря собственному механизму имитации данных и перехвата запросов легко восстанавливать ошибки, вызванные онлайн-данными.
  • И конфигурация wepbakc позволяет понять, что независимо от того, изменяете ли вы тестовый файл или тестируемый код, можно автоматически повторно протестировать его.
    • Небольшие советы: вы можете добавить тестовые случаиonlyилиskipчтобы избежать повторного тестирования всех вариантов использования в тестовом файле:it.only('只测试这个哟); it.skip('不要测这个');

кипарис три вопроса - как пользоваться

Установить

  • yarn add cypressилиnpm install cypress
  • После установки./node_modules/.bin/cypress installУстановите среду cypress (включая инструменты с графическим интерфейсом)

настроить

  • package.json: настроить способы запуска cypress с графическим интерфейсом и без графического интерфейса (терминал).
    "scripts": {
        "cypress": "cypress run",
        "cypress-gui": "cypress open",

⚠️ После настройкибеги первым yarn cypress[-gui]илиnpm run cypress[-gui](Квадратные скобки означают необязательный) для инициализацииcypress,Создание конфигурации и каталогов по умолчанию

  • cypress.json (тот же каталог, что и package.json): cypress обеспечивает более гибкую настройку, вы можете настроить поведение в соответствии с вашими потребностями, ниже приведена моя конфигурация для проекта
{
    "baseUrl": "http://localhost:8080", // 本地开发服务地址(webpack-dev-server)
    "integrationFolder": "src", // 自定义"src"为测试文件根目录,默认是"cypress/integration"
    "testFiles": "**/*.cypress.spec.js", // 自定义测试文件的匹配正则,默认是"**/*.*",即所有文件
    "videoRecording": false, // 关闭录屏功能, 如果开启录屏功能,记得将"cypress/screenshots"目录加入".gitignore",防止不小心将录屏加到git中
    "viewportHeight": 800, // 设置测试环境的页面视图的高度
    "viewportWidth": 1600 // 设置测试环境的页面视图的宽度
}
  • cypress/plugins/index.js: конфигурация среды выполнения Cypress, которую можно использовать для настройки веб-пакета и т. д. Ниже приведен пример настройки псевдонимов веб-пакетов. По умолчанию никаких настроек здесь не требуется.
// 参考官方例子地址 https://github.com/cypress-io/cypress-example-recipes/blob/master/examples/preprocessors__typescript-webpack/cypress/plugins/index.js
const wp = require("@cypress/webpack-preprocessor");
const path = require('path');

function resolve(dir) {
    return path.join(__dirname, "../..", dir);
}

module.exports = on => {
    const options = {
        webpackOptions: {
            resolve: {
                alias: {
                    "@": resolve("src"),
                    cypress: resolve("cypress")
                }
            }
        }
    };
    on("file:preprocessor", wp(options));
};

Все готово, тест тест тест

  • простой пример
describe('测试页面包含某元素', () => {
    it('有云 "前端哥哥们真帅,前端妹妹们真漂亮"', () => {
        cy.contains("前端哥哥们真帅,前端妹妹们真漂亮");
    });

    it('要有一个链接', () => {
        cy.get('a').should('have.length', 1);
    });

    it('不存在class含有abc的元素', () => {
        cy.get('.abc').should('have.length', 0);
    });
});
  • Интерактивный пример
describe('一起动', () => {
    it('获取输入框,输入文字并按enter键', () => {
        const text = 'not exist';
        // type api用法: https://docs.cypress.io/api/commands/type.html#Usage
        cy.get('input').type(`${text}{enter}`);
    });

    it('点击按钮', () => {
        cy.get('button').click();
    });
});
  • Пример имитации сетевого запроса

Совет 1: Сопоставление пути cy.route является строгим, поэтому обратите внимание на необходимость добавления подстановочных знаков. Такие какcy.route('/api/search', [])не перехватит/api/search?keyword=abc, будет только блокировать/api/search.

Совет 2: cy.routemethodОбратите внимание, что по умолчаниюGET,cy.route('/api/posts')а такжеcy.route('POST', '/api/posts')разные.

describe('要啥给啥', () => {
     beforeEach(() => {
        cy.server(); // 一定要在 cy.route 前调用
        cy
            .fixture('/posts/list.json') // 我们在 cypress/fixtures 内创建mock用的数据
            .as('postsData'); // 给 mock 数据取别名,以后 cy.route 使用
        cy
            .route('/api/posts', '@postsData')
            .as('getPostsRoute'); // 给请求取别名,以供 cy.wait 使用
    })

    it('进入列表页,拦截列表请求接口', () => {
        cy.wait('@getPostsRoute'); // 等待被拦截的接口请求完成

        cy.get('.post').should('have.length', 10); // 要有10条数据被渲染到页面上
    });
})
  • Пример реальной сцены: объединив все вышеперечисленные позы, мы теперь тестируем результаты поиска и работы страницы поиска.
describe('test search page', () => {
    // 几个 route 路径变量
    const searchRoutePath = '/api/items/activities?query=*';
    const deleteActivityRoutePath = '/api/activities/*/items/batch?num_iids[]=*';
    const undoActivityRoutePath = '/api/activities/*/items/undo';

    function search(keyword) {
        // 将搜索行为和等待搜索返回封装起来
        cy
            .fixture('items/activities.json')
            // 处理mock数据,只返回符合搜索结构的数据
            .then(data => data.filter(item => item.title.indexOf(keyword) !== -1))
            .as('searchResult');
        cy.server();
        cy.route(searchRoutePath, '@searchResult').as('searchRoute');

        const input = cy.get('input');
        input.clear(); // 清空输入框内文本

        input.type(`${keyword}{enter}`);

        cy.wait('@searchRoute');
    }

    before(() => {
        // 进行所有测试前,先访问搜索页
        cy.visit('/activities/search');
    });

    it('should show no data tip when search result is empty', () => {
        const text = 'not exist';
        search(text);
        cy.contains(`没有找到关于 ${text} 的结果`);
    });

    it('should remove activity from list when clean successful', () => {
        search('成功');

        cy
            .route('delete', deleteActivityRoutePath, {
                success: 0,
                fail: 0,
                waiting: 0,
            })
            .as('deleteActivityResponse');

        // within是让cy执行的context保持在'.activities-search'这个dom节点内
        // 默认cy的执行是以上一个cy命令结果作为context
        // 如 "cy.get('a'); cy.get('span')",cy会在上一个命令找到的'a'标签中查找'span'
        cy.get('.activities-search').within(() => {
            const items = cy.get('.result-item');
            items.should('have.length', 1);
            const applyList = items.get('.apply-list');

            applyList.should('not.be.visible'); // 每个数据项内详细内容区域是隐藏的

            const toggleBtn = items.get('.item-apply-count');
            toggleBtn.click(); // 点击显示详细内容区
            applyList.should('be.visible');
            applyList.children().should('have.length', 1); // 详细内容区内数据只有1条

            const cleanBtn = cy.contains('退出');
            cleanBtn.click(); // 点击详细内容区里的“退出”按钮

            cy.wait('@deleteActivityResponse'); // 等待“退出”请求返回
            cy.get('.apply-list').should('be', null); // 退出成功后,详细内容区数据减1,即空
        });
    });
});

Несколько обязательных к прочтению документов

О тестовом покрытии

В настоящее времяcypressВстроенной функции статистики тестового покрытия нет, для этого есть специальный выпуск на github, и в будущем их должно быть больше. Есть также несколько временных решений по этому вопросу, в настоящее время я склонен использоватьchromeПринесите свой, чтобы увидеть. Откройте в браузере GUI открытый тестdevtools, сократить доSources, нажиматьcmd+shift+p(пользователи Windows нажимаютctrl+shift+p),войтиcoverage, выберите Обновить и подсчитать покрытие выполнения кода.

untitled4

Итак, получить высокий

Ради высокого качества (измерения), количества (испытания), поколения (М), кода (М), выше. Если вам нравится интерфейсный ММ, вы можете обучить его вручную (¬_¬)


Эта статья была впервые опубликована на моем публичном счете: кленовый лист. Если вы заинтересованы, вы можете долго нажать QR-код ниже, чтобы следовать. ^ v ^