【问题标题】:What is the best practice of pass states between tests in Cypress赛普拉斯测试之间通过状态的最佳实践是什么
【发布时间】:2018-08-28 05:25:34
【问题描述】:

我想在每个测试之间传递/共享数据。在 Cypress 中实现它的最佳方式是什么?

例如:

 it('test 1'), () => {
   cy.wrap('one').as('a')
   const state1 = 'stat1'
 })

 it('test 2'), () => {
   cy.wrap('two').as('b')
 })

 it('test 2'), () => {
   //I want to access this.a and this.b

   //Also I want to access state1

 })

【问题讨论】:

  • 测试不应该共享状态——上下文是什么,你为什么认为你需要这个?
  • 如果要在其中使用 this.a,请避免使用速记箭头函数。使用 function() { 代替。 @jonrsharpe 有时您确实需要它:例如,第一个测试在单击某些内容时从剪贴板中检索某些内容,第二个测试使用此特定值来测试某些请求是否有效。
  • @trainoasis 那么您的测试依赖于彼此以及它们的运行顺序,这是一种反模式。
  • @jonrsharpe 同意了,但是您如何编写这样的测试而不模拟所有内容或进行 1 个大型测试? (部署后在 CI 中将其作为集成/验收测试运行)
  • @trainoasis 没有更多上下文很难说,但根据您上面的描述:只需进行一次测试。

标签: cypress


【解决方案1】:

正如abbr 在 cmets 中指出的那样,如果测试从不同的 url 开始,则使用全局变量共享值将不起作用。

所以这些不起作用:

  • 全局变量赋值和读取(不管它是否在describe/context块之外)
  • 依赖Mochathis.state(测试后清除)
  • 使用Cypressas

剩下的当然是文件。 Readwrite


describe("Test", () => {

  it("Can access 3000", function () {
    cy.visit("http://localhost:3000");

    cy.writeFile("shared.json", {count: 2})
  });


  it("Can access 8000", function () {
    cy.visit("http://localhost:8000");

    cy.readFile("shared.json").then(cy.log)
  });

});

【讨论】:

  • 请注意writeFile() 不适用于 ts 规范文件。
【解决方案2】:

对于 Javascript 变量,您可以这样做:

let state;

describe('test 1', () => {
    it('changes state', () => {
        state = "hi";
     });
});

describe('test 2', () => {
    it('reports state', () => {
        cy.log(state); // logs "hi" to the Cypress log panel
     });
});

.as() 似乎无法在 describe 块之间传递状态。

【讨论】:

  • 更好的方法是使用当前套件上下文:设置this.state,您可以跳过在全局范围内“让”(声明)变量。请注意,您必须使用function(){} 代替()=>{},以便分配this
  • 如果 it 测试导航到不同的域,这将不起作用。
【解决方案3】:

我可以看到对作者有用的答案,但是如果有人需要在不同的测试文件之间共享数据,解决方案是使用cy task method 并将数据存储在 Node 环境中,例如就我而言,我需要存储用户数据:

// cypress/plugins/index.ts
export default (on, config) => {
  on('task', {
    setUserData: (userData: UserDataType) => {
      global.userData = userData;
      return null;
    },
    getUserData: () => {
      return global.userData;
    },
  });
};

那么在测试用例中我们可以这样做:

// cypress/integration/login.spec.ts
describe('Login', () => {
  it('should work', () => {
    cy.visit('/login-page');
    cy.intercept('api/login-endpoint').as('postLogin');
    // login interactions
    cy.wait('@postLogin').then((interception) => {
      // intercept user data and store it in global variable
      cy.task('setUserData', JSON.parse(interception.response.body));
    });
    // ... further assertions
  });
});

稍后我们可以轻松检索这些数据:

// cypress/integration/otherTest.spec.ts
describe('Other test', () => {
  it('uses user data', () => {
    cy.task('getUserData').then((userData: UserDataType) => {
      console.log(userData);
      // voila! Stored data between two .spec files
    });
  });
});

您还需要为此扩展 Node TS 类型,但这个答案已经足够长了。

是的,我知道这根本不是一种编写测试的好方法,因为它使它们相互依赖,但有时应用程序中的长交互流程是必要的。

【讨论】:

    【解决方案4】:

    假设您正在尝试传递文本

    it('test 1'), () => {
      cy.wrap('one').as('a')
    }
    
    it('test 2'), () => {
      cy.wrap({ valueName: 'two' }).as('b')
    }
    
    it('test 2'), () => {
      //I want to access this.a and this.b
      cy.get('@a').then((thisIsA) => {
        cy.log(thisIsA);
        // logs 'one'
      }
    
      cy.get('@b').its('valueName').then((thisIsB) => {
        cy.log(thisIsB);
        // logs 'two'
      }
    
      cy.get('@b').its('valueName').should('eq', 'two')
    }
    

    【讨论】:

    【解决方案5】:

    我尝试了其中一些其他解决方案,但它们对我不起作用。也许最近的版本发生了变化。以下示例应该可以工作。请注意在两个测试中都使用了 function(),这使事情保持在 'this' 的上下文中。

      it('get the value', function () {
        cy.get('#MyElement').invoke('text').as('mytext1')
      })
    
      it('use the value', function () {
        cy.log(this.mytext1);
      })
    

    【讨论】:

    • 这对我来说是未定义的
    【解决方案6】:

    您可以像这样在步骤之间共享状态

    describe('A suite of steps', () => {
    
        it('visit a page and save the url', function () {
            cy.visit('/hello-world')
            // Store url
            cy.url().as('pageUrl');
        });
    
        it('load page url', function () {
            // Load the page from the previous step
            cy.visit(this.pageUrl)
        });
    })
    

    【讨论】:

      【解决方案7】:

      在解决这个问题时,我无意中找到了解决方案。不知道为什么会这样。导入任意json文件(此方案不会改变json文件)

      someTest.spec.js:

      import jsonFile from "../../fixtures/file.json"
      describe('Test some feature', () =>{
            it('test feature 1', () => {
              jsonFile.anyWalueYouWant="this is value from feature 1"                          
            })
      
            it("test feature 2", ()=>{
              cy.log(jsonFile.anyWalueYouWant)
          })
      
      })
      

      PS:anyWalueYouWant 不需要在这个 parameters.json 文件中

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-24
        相关资源
        最近更新 更多