Is there a way to run particular Protractor test depending on the result of the other test?

前端 未结 2 898
别跟我提以往
别跟我提以往 2020-12-22 10:45

This kind of question has been asked before but most of this question has pretty complicated background. The scenario is simple. Let\'s say we are testing our favorite TODO

2条回答
  •  遥遥无期
    2020-12-22 11:49

    Man, I spent good couple of weeks researching this, and yes there was NO clear answers, until I realized how protractor works in details. If you understand this too you'll figure out the best option for you.

    SOLUTION IS BELOW AFTER SHORT THEORY

    1) If you try to pass async function to describe you see it'll fail, because it only accepts synchronous function

    What it means for you, is that whatever condition you want to pass to it block, it can't be Promise based (Promise == resolves somewhen, but not immediately). What you're trying to do essentially IS a Promise (open page, do something and wait to see if the condition satisfies your criteria)

    if (conditionIsTrue) { // can't be Promise
      it('name', () => {
      })
    }
    

    Thats first thing to consider...

    2) When you run protractor, it picks up spec files specified in config and builds the queue of describe/it AND beforeAll/afterAll blocks. IMPORTANT DETAIL HERE IS THAT IT HAPPENS BEFORE THE BROWSER EVEN STARTED.

    Look at this example

    let conditionIsTrue; // undefined
      it('name', () => {
        conditionIsTrue = true;
      })
    if (conditionIsTrue) { // still undefined
      it('name', () => {
      })
    }
    

    By the time Protractor reaches if() statement, the value of conditionIsTrue is still undefined. And it maybe overwritten inside of it block, when browser starts, later on, but not when it builds the queue. So it skips it.

    In other words, protractor knows which describe blocks it'll run before it even opens the browser, and this queue can NOT be modified during execution

    POSSIBLE SOLUTION

    1.1 Define a global variable outside of describe

    let conditionIsTrue; // undefined
    describe("describe", () => {
      it('name1', async () => {
        conditionIsTrue = await element.isPresent(); // NOW IT'S TRUE if element is present
      })
    
      it('name2', async () => {
        if (conditionIsTrue) {
          //do whatever you want if the element is present
        } else {
          console.log("Skipping 'name2' test")
        }
      })
    })
    

    So you won't skip the it block itself, however you can skip anything inside of it

    1.2 The same approach can be used for skipping it blocks across different specs, using environment variable. Example:

    spec_1.js

    describe(`Suite: 1`, () => {
      it("element is present", async () => {
        if (await element.isPresent()) {
          process.env.FLAG = true
        } else {
          process.env.FLAG = false
        }
      });
    });
    

    spec_2.js

    describe(`Suite: 2`, () => {
      it("element is present", async () => {
        if (process.env.FLAG) {
          // do element specific actions
        }
      });
    });
    
    1. Another possibility I found out, but never had a chance to check is to use Grunt task runner, which may help you implement the following scenario

      • Run protractor to execute one spec
      • Check a desired condition
      • Export this condition to environment variable
      • Exit protractor
      • In your Grunt task implement a conditional logic for executing the rests of conditional specs, by starting protractor again

    But honestly, I don't see why you'd want to go this time consuming route, which requires a lot of code... But just as an FYI

提交回复
热议问题