Categories
Programming

Opening Right-click Menu / Context menu with Selenium WebDriver

Selenium WebDriver providesActionBuilder to perform complex user interactions with a web page. It allows chaining multiple actions together to perform a complex action.

You can create a complex action and execute the action (perform) it in the following manner. (Ruby)

driver.action.key_down(:shift).
              click(element).
              click(second_element).
              key_up(:shift).
              drag_and_drop(element, third_element).
              perform

 

The action to open the context menu is context_click() .

driver.action.context_click(webdriver_element).perform

By default, it will click on the middle of the element if you provide one.  Otherwise, it will click where the mouse pointer is at.

If you want to move the pointer to a specific location of the page before clicking, use methodmove_to.

 

If you want to select an item from the context menu use arrow keys and enter then perform the action. You can also further pinpoint the cursor position by using  custom position from your element reference

page.driver.browser.action.move_to(webdriver_element, 5, 10)
 .context_click
  .send_key(:arrow_down)
 .send_keys(:enter)
 .perform

 

Ref: http://www.rubydoc.info/gems/selenium-webdriver/Selenium/WebDriver/ActionBuilder

Categories
Programming

Think differently when the current tests fails

This is a lesson learned from work. SO we use Rials in our project at the workplace. SP for a new requirement, we had to have a validation for a particular attribute of a model.   The requirements were specific on where the validation should happen. Say for example for what controller actions.

However, the initial idea was tho have the validation at the model so that it will be validated on create and update. The idea was that every controller action that matters the new attribute validation would automatically be validated.

The approach was working great. However, after the existing tests suite has run, the results were about 70% failure. So we looked into the test code and noticed that the attributes set for the models were not following the rule. Therefore the initial thought was to fix the specs and make them pass. So we spent several hours altering the specs and running them to make sure they pass. Then we came across a test that acutally indicated our approach caused an existing functionality to break. Meaning that the rule should not be validated when performing that particular functionality.

So then we thought about a different approach and ended up using contexts in Rails. There we were able to tell the model only to validate the attribute when it is in the given context. As a result, there were only few tests that failed at controller level testing. We quickly fixed them and added specific test scenarios to cover the new requirements.

So lessons learned:

When the code change breaks a lot of existing test, it is most likely because that the app functionality is broken. So think of the bigger picture of the code change and come up with a solution that would impact less part of the application as a whole. 

Categories
Programming

Be careful when using loops in Jasmine specs

Your test automation code is an important tool to evaluate your application.  You must ensure your test code is working/testing as you want it to be. the automated tests give confidence for the developer that the application behaves as expected and things are not broken after they change the code.

Recently, at our QA phase, the QA found a bug that should have been caught from our test automation. Therefore being suspicious I looked into the code.  Interesting enough, the way we used loops along with test blocks were not testing as we wanted. Below is an example of a test block with the bad approach we had. Then I listed down a working approach using loops.

describe('Bad Spec', function () {
 for (var i = 0; i < 3; i++) {
   console.log('Iteration value outside test: ' + i);
   it ('bar', function() {
     console.log('Test is evaluated. Iteration value inside test: ' + i);
     expect(true).toEqual(true)
   });
 }
});

The following is the console output. Notice that the value inside the test block is always the same value.

Iteration value outside test: 0
Iteration value outside test: 1
Iteration value outside test: 2
Test is evaluated. Iteration value inside test: 3
Test is evaluated. Iteration value inside test: 3
Test is evaluated. Iteration value inside test: 3

 

Here a solution is to use a function

describe('Good Spec', function () {
  function goodRunner(itemValue) {
    it ('foo', function() {
      console.log('Test is evaluated. Iteration value inside test: ' + itemValue);
      expect(true).toEqual(true)
    });
  }
  for (var i = 0; i < 3; i++) {
    console.log('Iteration value outside test: ' + i);
    goodRunner(i);
  }
});

Now the output looks as follows.

Iteration value outside test: 0
Iteration value outside test: 1
Iteration value outside test: 2
Test is evaluated. Iteration value inside test: 0
Test is evaluated. Iteration value inside test: 1
Test is evaluated. Iteration value inside test: 2