
Site auditing modules in Drupal need to be installed in the codebase and require certain modules to be present on the server for gathering the required metrics. Moreover, traditional site auditing tools cannot be customized. In this blog post, we will be exploring Drutiny, an open-source Symfony Console based application used to audit Drupal 7 or Drupal 8 sites.
Drutiny stands for Drupal and Scrutiny. It offers an automation layer for auditing and reporting the Drupal 7 and 8 sites with a library of predefined policies. All checks are run from the outside looking in and require no special code or modules to be enabled on the remote site. This means you can audit all environments from development to production and not have any lasting performance degradation.
Drutiny does all the checks from the outside, which means that we don’t need to run the code or enable the module on the remote site or server.
1. You can audit all the environments from development to production and there will be no performance degradation as it will not put the load on the server
2. Drutiny also integrates seamlessly with the other tools to ensure that you have maximum flexibility when it comes to running checks, e.g.
3. You can run site audits against Drupal 7 or Drupal 8 sites using the same Drutiny codebase
4. It ensures the site state against performance and security best practices
5. It offers automation of sanity testing
6. Different types of report formats are available with Drutiny
Step 1: Drutiny can be installed in 2 ways:
In your project folder using composer - Add the composer dependency.
OR
As a standalone tool - Clone the Drutiny framework using composer
Note: We are using a standalone tool installation approach in this blog.
Step 2: Installing Drush for getting Drush aliases
The version of Drush to be used will depend on the site you're auditing. For instance, Drush 8 is recommended for D7 and D8 sites.
Step 3: Test the Drutiny installation
Step 4: Download Drush Aliases from Acquia Cloud (Optional)
Download the Drush 8 aliases for all of your sites and extract the archive into $HOME
This folder will contain two hidden folders named .acquia and .drush. Both of these folders should be placed in the $HOME directory on your system. The .acquia folder contains your Acquia Cloud API credentials and the .drush folder contains your Drush aliases for the sites you currently have access to on Acquia Cloud.
Note: Step 4 is only useful to get site aliases for the multiple sites on the Acquia cloud.
When you're running Drutiny as a standalone tool use this basic command

Drutiny works with Policies and Profiles. These are the key elements of Drutiny.
Policies are structured YAML files that provide the human-readable context for an audit. You can see the predefined list of policies with the policy:list command.
Syntax:
Example: If you want to make sure that user # 1 is locked down, Cron is running, JS aggregation, Certain Modules are enabled or disabled.

You can view the policy details using thepolicy:info command and just pass the policy name.
Syntax:

The user can run the single policy audit against a site using policy:auditcommand where policy is the name of the policy to run and the target is the Drush site alias.
Syntax:
Examples

In multisite scenarios, you will need to specify which site to connect to via a --uri option.

A policy may contain parameters that can be customised at the time of execution. To know what parameters are available, use the policy:info command

In this policy, the max_size and warning_size parameters can be specified. These parameters can be passed in at runtime like this:
Profiles are a collection of policies that audit a target against a specific context or purpose. Examples of the profile are Production-ready Drupal 8 site and Security or performance audit.
To view the list of available profiles in Drutiny, use the command profile:list
Syntax:

To know which policies are included in the profile, use the command called profile:info
Syntax:

The profile:run command allows you to run a profile against the target
Syntax:


The user can create a profile that is specific to their internal guidelines with the desired policies. Profiles are YAML files with a file extension of .profile.yml. To create a profile, use the command called profile:generate
Syntax:
The Drutiny will prompt you for the mandatory fields such as profile title, brief description about the profile, policies to be added in the profile and the file location.

And further, you can use your custom profile in the same way as built-in profiles.
Drutiny allows the use of 3 types of reporting formats:
If you do not specify any report format, the CLI format will be used by default.
You can use the following parameters for the reports:
Syntax:

Open the HTML report in your browser to view the report. From there you can also print it to PDF. Refer to the report attached in the image below.

Happy Testing!

Opening an URL in a new window or new tab is one of the features provided by Selenium 4. In Selenium 3, we can achieve this by performing switch operation using the WindowHandle method. In Selenium 4, this is going to change by using the new API newWindow.
Let’s consider a test scenario where you have two interfaces, one for admin and another for users. As a user, you need to perform some steps then you have to log in as an admin. As an admin, if you do some configuration changes, these changes should be visible to the user. In such cases, we can open the website in one window and log in as a user. Then we can open the same website in another window and log in as an admin. Once the admin performs the configuration changes, we can go back to the user window and verify whether the changes are reflected.
In Selenium 3, we needed to create a new WebDriver object and then switch to a new tab or window. But with Selenium 4, we can avoid creating new WebDriver objects and directly switch to the required window. We have a new API called newWindow in Selenium 4. This API creates a new tab/window and automatically switches to it.
New Tab
Here’s how you can create a new tab in Selenium 4 and switch to it:
Let’s consider that you are on the QED42 homepage and you need to switch to another URL in a new tab.
Here is the snippet to open an URL in the new tab:
New Window
Creating a new window in Selenium 4 and switching to it:
Similar to a new tab, here is the snippet to open an URL in the new window:
Switching back to the Original Window
Suppose, there are multiple tabs and windows open and you need to switch to a particular or original window/tab. This can be achieved using driver.switchTo().window(windowHandle) method.
Let’s implement the below steps to understand it:
Below is the console output:

Point to note: Closing a window will leave WebDriver executing on the closed page and will trigger a No Such Window Exception. Therefore, you must switch back to a valid window handle in order to continue execution.
The sample codes are available at the Github repository here.
Selenium 4 provides better window/tab handling using a new API. We can now create a new tab/window and automatically switch to it with fewer lines of code and without creating a new WebDriver object.

We were working on building a site that was a bridge between interested customers and the car dealers/OEMs. All the data related to a vehicle which will be useful for a customer was displayed on the website. The data from interested buyers was also captured through a form and shared with the relevant dealers/OEMs.
As the project was growing day by day, new features were getting added. So, manual regression testing was becoming a lengthy process before every release which happened twice a week.
The website was on ReactJS. We were using Cypress for automation because it is purely based on JavaScript and uses a unique DOM manipulation technique and operates directly in the browser. Cypress also provides a unique interactive test runner in which it executes all commands. We started automating the regression test cases according to the priority of the module. The regression suite was integrated with CI. Before every release, it was mandatory for the regression suite to pass in the CI.
There were two releases in a week, which meant that new features were added every time. Suddenly we started facing issues on CI and test cases started failing randomly with timeout errors.
We tried running it multiple times but test cases that were passed earlier start failing, on every run we were seeing various sets of test cases failing which were passing before, the result was not the same in every run.
We suspected that there was some issue with the Cypress tests, so we tried to replicate the issue on our local machine. But many test cases randomly started giving timeout errors on our local machines as well.
All the commands in Cypress have a default timeout that means Cypress will wait for a definite time for the command to get executed, all the DOM-based commands have a default timeout of 4 seconds.

For example cy.get(‘#firstname’), in this case Cypress waits up to 4 seconds for id to be present in DOM. Similarly for every assert command Cypress waits up to 4 seconds by default. It looks for the element up to 4 seconds and if it is not present, Cypress throws an error 'Timed out retrying after 4000ms: Expected to find element: #firstname, but never found it'.
So the conclusion was that our Cypress test suite failed due to the timeout issues. When testing a web application, a timeout error can occur when the application performs an asynchronous operation that needs to finish before the application state and user interface (UI) are ready for testing. If a command or assertion in Cypress is executed before this operation completes, the test will mostly fail.
However, if the time taken by this operation varies, sometimes it may complete quickly enough to pass the test. This inconsistency creates a situation where the test results become unreliable or "flaky."
On looking at the timeout errors, our first approach was to increase the default timeout to 20 seconds, just to check if the test cases started passing. Yes, all the test cases started passing after we increased the default timeout.
Now, the next question was what should be the value of default timeout? We thought of checking the performance of our website. We found that the average time taken by all the pages to be interactive was around 8.5 seconds.

When we increased the default timeout to 10 seconds in cypress.json our test cases started working on CI.
We can modify the default timeout for a single command by passing a timeout parameter, for the example in this contact form , if we want to add a 10 seconds timeout we can modify it as below:
Here in the above code we have given different timeouts for each command, so cypress will wait for the wait for a given time (only if an element is not found) before moving to the next command.
We can also globally configure by setting these timeouts in cypress,json which will by default add a 10-second timeout for all the commands.
Lets understand cy.wait() , this will wait for specified milliseconds or wait for an aliased resource to complete to move forward . Here we can specify the time period. If needed this is simple way to specify wait time Example for 5 seconds
In the example above:
By using cy.wait() with an alias, you can ensure that Cypress waits for a specific condition before moving on to the next steps in your test. This is useful when dealing with asynchronous operations and waiting for certain values to be available or updated.
We were continuously adding new features to the site, due to which performance of the site was impacted, and our Cypress tests started failing because the time required for rendering the elements on the pages was high. The real issue was with the performance of the page. These reports were shared with the development team and it was decided to improve the performance of the websites in the next sprints.
It's not always that your test needs to be fixed. We need to identify the root cause and provide feedback to the team.

With almost 3.5 million smartphone users, it is no surprise that the mobile application industry is flying high. App usage and smartphone penetration are growing at an exponential rate. If you take a minute and look around, you will find that almost everyone is glued to their screens. We use our phones while at work, at home, lying down in bed, and even while eating. A pertinent question to ask would be: what exactly do we do on our phones?
Most people use applications on their phones, which exponentially increases with the time they spend on their mobiles. There are over 3.48 million apps available on Google Play Store. According to recent studies, millennials have around 35 to 40 apps on their phones, out of which they spend time on approximately 18 of them.
Since many apps get developed every day, testing these apps is crucial. If an app has a glitch before it gets launched in the market, that error needs to be corrected. Mobile app testing ensures that the apps get tested for functionality, consistency, and usability. However, performance and speed are also vital factors that are checked before launching an app.
Every app goes through a performance test. A performance test is different from a functionality test. A functionality test determines whether the app is responding correctly or not. A performance test determines the various other aspects of the app, like its speed.
Performance testing is vital since it establishes the durability of an app over multiple areas. QA engineers simulate real-life usage environments to run these tests. It helps them to experience for themselves what a user will feel while using the application. This is the prime difference between functionality testing and performance testing.
Mobile app performance testing determines various arenas like speed, user-friendliness, volume testing, scalability, usability testing, load testing, stress testing, etc. When the application goes through performance testing, it is crucial to ensure that the app works according to SLA (Service Level Agreement). SLA is a written agreement that specifies the service committed by a vendor to its user in terms of quality and quantity. The test should also ensure that the app will work even at the time of low connectivity.
The overall process of mobile app performance testing includes:
Mobile performance application tests determine the application's overall performance, which is a big part of your business. A performance test helps to determine the application's working in unfavorable conditions like low network strength, sharing resources with multiple applications, etc.
An app is created with a purpose to fulfil some desire of its user. For example, apps like Facebook, Instagram, and Snapchat connect users from across the world. Apps like Zomato and Swiggy help users order food; Weather or Forecast offers information about the weather. To ensure that an app perfectly performs its functions, a mobile app performance test is crucial. Sometimes when an app performs poorly, most of its customers never use it again.
A study found that 9 out of 10 times users stopped using a particular app because it responded poorly.
Therefore, it becomes vital to test an app before launching it.
Let us understand this with another example. Consider two companies, A and B, that are new in the market. Their prime business takes place through their online protocol and apps. Both the companies deal in styling products. Both company's apps are user-friendly, but company A's app does not work efficiently when connected to a slower network or changes drastically when the location of the user changes. Because of these glitches, company A is losing its customers, and company B is gaining an advantage. It will drastically affect the business of company A.
To avoid such hurdles in your business and promote growth, a mobile app performance test is indispensable.
Every app that gets measured can improve as well. There is always room for improvement. An app has to go through many levels of testing, modifications, and re-testing to become high quality. To assess the standard of apps, we must first understand the different performance metrics.
Testing a mobile app can be very challenging. While undergoing performance tests, many issues arise related to the load, speed, response time, etc. A few of these challenges are listed below:
Planning and forming a good strategy for the performance test is a very crucial step. Creating a fool-proof strategy plan from scratch can be difficult. But the good news here is that testers and developers can examine existing performance test samples.
These are the steps required for planning:
There can be various factors affecting the performance of a mobile app, such as:
To ensure that the app is indeed useful and delivers its intended result, mobile app performance testing is a necessary step. Mobile app performance test helps to check various metrics such as average crash time, the response time of the app, network errors. It also helps in finding solutions to these problems. For a business, this is an essential step since its credibility lies in the app. The scale of growth and revenue of the company also depends upon this. If the app performs well, it ensures more downloads, recommendations, and popularity, leading to booming business. When developing a performance test, the developer has to carefully take into consideration all the necessary fields such as different devices, identify the key performance factors, prioritize scenarios. Planning and strategizing are very crucial. We believe in the deep integration and testing of an application to provide the best possible stability and performance. With our end-to-end quality assurance and testing services, we promise to deliver error-free and high-performing mobile apps. To know more about our quality assurance services click here.

Sprint Zero is officially not a part of the agile methodology, but it is a pre-planning process for a project. It usually takes place before the formal start of a project. The goal of Sprint Zero for the development team to come together and begin the project exploration. The quality of any project is crucial and should start from the very beginning. And hence it is imperative that your QA team should also be a part of Sprint Zero.
As per STLC (Software Testing Life Cycle), testing starts with the first phase called requirement gathering and analysis. QA engineers can deliver a quality product when involved in this first and very important phase, from where the testing starts. The main focus is to carry out testing as early as possible because as we know finding and fixing the defects in earlier stages of the project is recommended. And thus, QA engineers must participate in Sprint Zero.
Of course, these activities can vary from project to project as per the types of the requirement you will get. Basically, Sprint Zero helps to set the direction of what testing needs to achieve and how testing needs to be carried out throughout the sprints. It’s worth saying that QA's role is very crucial in building a quality product and thus lets start participating in Sprint Zero and contribute towards the project's success.
Happy Testing!

We often come across pop-ups while browsing websites. We usually accept the cookies without knowing anything about them, to browse the website without any hiccups. So, let’s understand what browser cookies are and how to test them.

A cookie or browser cookie is a small piece of data from a specific website that is stored on the user’s browser while they access that website. In other words, a cookie is nothing but the user's identity for their browser. This information gets saved in the form of a text file by the web server and can be used to interact with the server through the browser. It makes it easier for the browser to remember the user and the navigation they do, on their next visit.
Browser cookies have different functions such as:
Cookies were designed to identify the system, however, they are now also being used to keep a track of user’s online activity. This can be a threat to user’s privacy, depending on how the website decides to use this information.
Cookies contain user's information that can be used to communicate between different web pages and track a user’s website navigation. To avoid any security threats, it is important to keep a check on how cookies are written and saved in the system. Since some functionalities might behave differently when cookies are set, it’s crucial to test the cookies to verify how an application behaves and responds based on the status of the cookie.
Let’s understand how cookies work with an example: Suppose you visit an e-commerce website for the first time. The website will assign a cookie in your system as a unique identifier. This unique id is then used to keep track of your overall browsing session from start to finish. It keeps a check on all the products you browse or add to your cart and use the information to suggest similar products to you.
In this scenario, the cookie is specific to the website and can’t track you on a different website.
Go to the Application Tab and click on the Dev tool, there you can find the option to access the browser cookie.

Name: This is the cookie’s name, which is set by the server
Domain: This attribute is used to indicate if the browser should accept cookies or not
Let's look at some scenarios of different domains:
Expires/Max-Age: This attribute indicates the expiration date of the cookie. This is mostly a session cookie, which means the cookies will expire when the user closes the browser window.
HTTPOnly: If a value of this attribute is true, it means that the cookie can only be used by the website built over HTTP and not by the javascript code.
Secure: If the value of this attribute is true, it means the cookie can only be used over a secure connection, i.e. HTTPS.
SameSite: This attribute is used to improve cookie security by preventing cross-site request attacks and privacy leaks.
The values of SameSite are the following:
Now, let's take a scenario where the cookie is set as SameSite=Strict. The site you are browsing has a button called “Login” which displays an image to the user. The user can access the image only when the set cookie is sent from the same site and not from any third-party website.
Strict prevents the cookies to be sent over on a cross-site request.
Let's look at some more attribute values and the respective scenarios:
Domain = ‘.example-a.com’ SameSite = Lax;
Suppose a user is browsing an example-a.com website that contains a link from another example-b.com website. If the user accesses that link to go to example-b.com, then it's called a cross-site request. The Lax cookies will be sent to example-b.com, but not the Strict cookies, as this is a cross-site request.
1. If the website uses cookies for its major functionality, then it will ask you to enable the cookies to function properly.
2. That page must not crash if you disable the cookies.
There are multiple extensions or plugins that can be used to test or edit the cookies. The most common one is EditThisCookie. This is a cookie editor and a Google Chrome extension.
Suppose you are browsing the site https://en.wikipedia.org/wiki/Main_Page. The EditThisCookie chrome extension will enable you to test or edit the cookies.

The pop-up screen for this extension displays the options to edit or test the cookies as per the requirement.
Yes, every tool in automation testing allows managing the browser cookies. It helps in automating the website functionality that is dependent on the cookie. Sharing some guideline documents of what these tools are and how the cookies can be managed in the automation test suite.
Selenium - https://www.selenium.dev/documentation/en/support_packages/working_with_cookies/
Cypress - https://docs.cypress.io/api/cypress-api/cookies.html#Syntax
NightWatch - https://nightwatchjs.org/api/commands/#cookies-headline
WebdriverIO - https://webdriver.io/docs/api/browser/getCookies/
Happy Cookie Testing!

Acquia Site Studio (previously known as Cohesion) is a low-code Drupal-based platform that allows content editors and marketers to create unique websites using components and layouts. It uses a drag-and-drop editing feature which provides fast and seamless learning for QA Engineers having less coding knowledge. We recently delivered a low-code, enterprise scalable, self-service platform and CMS for a German multinational pharmaceutical and life sciences company to build 1000+ websites and migrate 170 consumer brands. Based on our experience, we will be describing our QA process and the best practices for Site Studio testing.
We applied the W2H1 (Why-What-How) approach for understanding Acquia Site Studio from a Quality Assurance perspective.

Site Studio (cohesion) provides a wide range of in-built form elements that can be used to create custom components as per project requirement. Site Studio also provides options to create various templates for the website - Master, Content, View and Menu Templates.
For example, a QA Engineer has created the header menu links at the backend but it is not rendering as expected at the frontend. In such cases, the QA Engineer should know which template to refer to, to identify the cause of the issue.
Site Studio provides the ability to create components with very less code knowledge. This enables QA Engineers without much coding knowledge to create components and perform testing efficiently and effectively.
Let me share an example of our project, we were required to validate if the content of the “Modal” custom block reflects properly on to the frontend. This “Modal” component was yet to be developed by a 3rd party vendor.
So we created a component using the Site Studio “Modal” element and used it to validate the “Modal” block feature on the frontend!
This knowledge helps the QA Engineer to validate if the component built meets the requirement and serves the purpose of reusability. In addition to this, it helps the QA Engineers to provide a workaround for any enhancement/condition-specific use cases, using the existing components.
In our project, there was a requirement to launch a modal pop-up on clicking a menu link. In this case, a QA Engineer should understand how to sync the Drupal menu link and the Site Studio Modal component. And should also validate that clicking a menu link triggers the launch of the correct modal pop-up.
Style Guide Manager helps to change styles and appearance depending upon the theme/subtheme. This would help the QA Engineers to validate if the changes made to style values in SGM are reflected correctly on the frontend for the corresponding theme.
Acquia Site Studio facilitates sharing of components, templates, styles and configurations with other websites using the import/export package option.
QA Engineers can import and export packages using either UI or Drush. For Site Studio projects, QA Engineers usually need to validate that the latest package (provided after each release) is imported and rebuilt successfully on the website. And the updated package is not breaking existing features.
This also reduces the dependency of the QA Engineers on the dev team for importing packages on various websites.



Regression testing is to check if the modification/upgrade of the application has not led to a functional break. This testing involves the below activities:
Integration Testing is carried out once the individual components have been unit tested and are working as expected; without waiting for the entire system to be ready. This ensures early detection of defects and also helps in isolating the defects to particular component interaction.
For example, we had to ensure that the “Product Teaser View” and “Slider component” are ready at Drupal and Site Studio end respectively. QA had to validate if fields of the product teaser view are rendered correctly in the slider component. And an end-user can slide through products and navigate to the product's PDP page via click event.
The user interface is crucial when it comes to creating a reliable website. To ensure all the elements of the front-end work as expected and are displayed equally well for users across all devices and browsers.
There are a couple of factors to validate as part of UI testing:
When content is translated into languages other than English, it gets expanded in length, this might affect the UI/UX of the website. English texts are usually short compared to other languages. Therefore, translated content leads to truncation, overlay on or under other components and so on.
Testing of components using Right-to-Left language requires special considerations such as the focus on text alignment, ordering of components within the layout, positioning of buttons, dropdown, data entry fields, so on. Therefore, QA Engineers need to make sure that no components and design are breaking for multilingual and RTL language sites.
To achieve enhanced product quality and team agility, it is always ideal to automate regression testing. The regression test suite should include both functional and UI test cases.
Functional regression testing is essential for verifying that components of our system are working as expected after a code change. For Site Studio, we automated functional regression test cases such as the creation of contents using components, interaction with components and so on, using an automation tool called Behat.
After every release, we ran the automated functional regression test suite. This ensured that existing core features were working as expected and also increased the chance of detecting bugs caused due to the change.
Apart from having fully functional components in the system, it is also important to be concerned about the user interface. Styling or CSS change can have undesirable effects on other components and might break responsive pages at different resolutions. Therefore, we need visual regression testing.
Visual regression testing is a visual comparison between the base and test image versions. However, today there are a huge range of browsers, devices and screen resolutions and testing them manually has become impossible. Therefore, we need to automate this testing using a visual regression framework/tool such as Backstop JS.
Brand sites have specific design requirements apart from the Master Design System. When a new package is rolled out on multiple brand sites, we need to test that components and styles are rendering as expected on each brand site. This increases the testing effort and time. To minimize the testing efforts and find UI bugs, we can use visual regression testing tools.
QA Engineers need to verify that the package import and rebuild are successful. Sometimes, a package is imported successfully on the website but the rebuild fails. QA Engineers also need to ensure nothing breaks after import and rebuild, from both style and feature perspectives.
Site Studio upgrades sometimes have an impact on the websites. Therefore, we need to perform regression testing on websites using upgraded versions on lower testing environments, to identify if there any impact or risk. Once the entire checklist is tested and passed, upgrading is performed on higher environments.
For example, with Site Studio 6.1.1 upgrade, there was a change: “Themes with Acquia Cohesion enabled and not set as default will no longer generate assets automatically”.
In our project, this impacted the websites using the sub-theme and as a result, components were not rendered correctly for that theme. The solution was to check the Build Site Studio assets checkbox in the appearance settings of the theme under the Site Studio section. Once this solution was applied successfully to existing sites using a non-default theme and to new sites, an upgrade was performed on higher environments.
API Outage of Site Studio has a huge impact especially when we are developing, testing and deploying features. This blocks the activities related to site studio testing. Initially, when we started to use Site Studio in our project, we often faced API Outage. Now, Site Studio is very stable and consistent in terms of API Outage.
We covered the purpose and process of understanding Acquia Site Studio from a Quality Assurance perspective, along with the test approach that should be applied to any Site Studio and Drupal integrated project. We also focused on the areas of impact and the challenges that we encountered in our project. If you’ve worked on a QA project for Site Studio, we would love to hear from you!
Happy Testing!

Migration testing is to ensure that your application gets migrated from one system to another without affecting the legacy data and the functionalities. While the migration is in process, the testing team needs to ensure the integrity of the system is intact and that there is no data loss while migrating the data.
Data loss is the most common issue we come across in Migration Testing, and when we have huge data to be migrated we cannot completely depend on manual testing. Because it becomes impossible to verify content and compare it with the source data. If we have automation in place to check the vast amount of data, it will help us find data loss in less time and will give us more confidence in the migrated system.
Let me share an example, we had a requirement to migrate a university site from Drupal 7 to Drupal 8. Since it was a university site it had heavy data/content including various courses, programs, staff, faculty, events etc. and we needed to ensure that all the data gets migrated with no data loss.
We had around 24 content types and each content type having thousands of nodes. It was impossible to verify this number of nodes manually. So we created an automation framework that helped us verify all nodes.
We started exploring various options using existing functional tools like Behat, Selenium, Cypress, etc. but we wanted to avoid the browser interaction in this data verification process because visiting node pages and verifying data would require a lot of time and when it comes to 1000+ nodes it could take hours. Choosing functional tools which use browsers never suffice our needs when it comes to large amounts of data.
Our source (D7) and destination (D8) were in MySql DB format, so we decided to create a custom tool to verify the data migration. We created a Drupal module having a custom Drush, command that would verify the migrated data. Helping us execute test fasters and at the same time utilise the existing drupal functionalities and its framework in our tool.

We created the custom Drush 9 command - “drush migration:test <content_type_machine_name>”
The Drush command accepts two parameters - a content type name and the number of nodes to check, by default it would check all nodes.
Apart from this, we maintained two DB connections in the Settings.php file by adding another array for D7 - DB connection.
We required a few inputs before running the migration tests - we needed the information of each content type and its field mapping in D8. This helped us compare the data with the exact node and data inside each field.
We then created Mapping files in YAML format, each of these files was named in <content_type_machine_name>.yml format, each file had the following format:
The Fields array holds all the information about the fields from D7 to its corresponding D8 field and the Drush command uses these YAMLs as a source of input before querying the DB’s.
Each field type has specific columns in DB, and those particular columns were used to verify the data.
For example, each field having type text (we get this field type from a mapping file) will have a field table with column name as - <field_machine_name_value> as a column that will hold the actual data. We created field_type.yml which holds all the column information of each field type that will be used to fetch specific data for comparison.
Here the {fieldname} will get replaced with the actual field name from the mapping file. We had to maintain field type for D7 and D8 both because in D8 few column names were updated.
To get the node data from the DB, we created a custom function that will dynamically create SQL queries based on mapping and config files for both D7 and D8 databases and fetch the values.
Since we have different naming conventions for tables in D7 and D8 we require to maintain the version name and change the prefix of the field table based on a version like D8 store field values in node_<field_name> and D7 stores in field_data_<field_name> same goes for storing node values D8 uses node_field_data table where D7 uses node table.
We used the fields option for mapping files and for each field, we use the field config file mentioned above to fetch the column of respective fields. Once all the tables and columns are collected we Command-Line built and executed the query on the respective database.
Once the data for both D7 and D8 is fetched, both the sets of arrays were compared and failed nodes were logged in the reporter which then generated the HTML report after comparing all the nodes.
Reporting was important so all stakeholders could understand the reports and identify the issues mentioned in the reports. We created reports in 2 formats:
- The Test Information section provided the basic information of the test and content under the test like content name, migration table, mapping file, etc.

- The Result Section provided a pie chart with the exact number of pass and failures.

- The Fields Report Section highlights the fields’ columns that failed for a particular number of nodes.

As shown in the above image, the profile visibility field has seen issues with around 10000+ nodes.
- Issues section - This shows the values that are missing or are not matching with the D8 migrated data.


Referring to the above images - we can go through each node and verify the issue and compare the D7 and D8 values that are seen after migration. For example in the above image for field_tags, the tid is missing in D8 which means this tag was missing in the node after migrating it to D8.
Because of the client requirements and changes in data format, there were various false positives. There were fields from D7 which were stored in different formats in D8. Following are a few examples:
To handle such false positive scenarios we added one more step of preprocessing before comparing the D7 and D8 data. Prepossessing functions were called based on the field type, field name or content type.
The prepossessing class had all preprocessing functions based on the specific field type, field name or content type. These preprocessors updated the D8 data as per changes required and returned the values of the updated array.
Here’s an example of Link Preprocessing for one field:
D7 had a list of field collections that were used in nodes, these field collections were going to get merged as paragraphs in D8 and had around 44 types of field collections, which were directly mapped to paragraph fields. To handle this separately we directly verified field collections data with paragraphs using different Drush commands because the structure and way of storing data in field collections and paragraphs were different from normal fields.
So we created 2 YAML fields which stored a list of field collections fields and another for paragraph fields.
An example of FieldCollection.yml:
Example for ParagraphType.yml
As shown above, each field collection type had a paragraph type mapped and every field in field collection was mapped to fields in paragraph type. The rest of the process was the same as for nodes; only table and column prefix would be changed.

In our previous blog post Automate SEO factors testing using Behat - Part 1, we covered SEO factors - meta tags, keyword and image optimization. Here we are going to cover the remaining SEO factors.
Redirects are the technique to forward users and search engines from an old URL to the correct URL.
Types of Redirection:
Sample Scenario:
Given I am on “/redirect.php”
Then the response status code should be 301
And I should be redirected to “/redirect/redirect.php”
RedirectContext method:
The robots.txt is a text file that instructs the search engines crawlers which page of the site is accessible. In a robots.txt file, we can specify allow or disallow rules for all user-agents or specific user-agent(s). When the file contains a rule that applies to only one user-agent, a robot will follow the URLs/sitemap specified for it. To ensure robots.txt file is found, always include it in the root domain. In case of robots.txt file is added in the subdirectory, it would not be discovered by robots and the complete page would be crawled.
Basic format:
User-agent: [user-agent name]
Disallow: [URL string not to be crawled]
Allow: [URL string to be crawled]
(Note: Only applicable for Googlebot)
Crawl-delay: [Time in seconds for the crawler to pause crawling the page]
Sitemap: [XML Sitemaps associated with the URL]
Sample Scenario:
Given I am a "Googlebot" crawler
Then I should be able to crawl "/crawl-allowed"
RobotsContext method:
The sitemap is an XML file that provides search engines with the list of URLs, available for crawling on a particular website. A sitemap is mostly useful when a website is new with few links or content is large or it has rich media content. In such scenarios, a sitemap provides Google with pages that are more valuable and informative on the website.
For large websites, we may end with many sitemaps. Here, we can split large sitemaps using the sitemap index. Following is the XML tags for sitemap index file :
Sample Scenario:
Given the sitemap "/sitemap/valid-sitemap.xml"
Then the sitemap should be valid
SitemapContext method:
Extension module “marcortola/behat-seo-contexts” also provides the following validations:
Schema.org is a collaborative effort between Google, Bing, Yandex, and Yahoo to create structured data markup. This will provide information to search engines about the page and enhance rich results experience.
Sample Scenario:
Given I am on homepage
Then the page HTML markup should be valid
HTMLContext method:
HTTP status code is a three-digit response sent by a server for a browser's request.
Common status code classes:
We can use the existing step - “Then the response status code should be 301”, to validate HTTP response code.
Hreflang tag is an attribute which helps search engines to show the correct version of the page based on a user's location and language preferences
Format: <link rel="alternate" href="http://example.com" hreflang="en-us" />
One of the rules is that hreflang tags are bidirectional/reciprocal. Bidirectional means - When an English page is linked to Spanish page, then Spanish page must link back to the English page.
HTML Markup:
<link rel="alternate" href="https://www.qed42.com" hreflang="en" />
Sample Scenario:
Given I am on “/valid-hreflang.html”
Then the page hreflang markup should be valid
LocalizationContext method:
Page Speed (page load time) is the measure of time taken to fully load content on a page.
Some of the ways to increase page speed :
Extension module provides performance context that covers - Testing HTML minification, Testing CSS minification, Testing JS minification, Testing browser cache and Testing JS loading async or defer. Below is the snippet for CSS/JS minification.
Sample Scenario:
Given I am on "/performance/html/minified.html"
Then HTML code should be minified
PerformanceContext method:
A URL (Uniform Resource Locator) is a human-readable text that specifies the location of the webpage on the internet. A URL has the following basic format: protocol://domain-name.top-level-domain/path
SEO best practices for URL optimization:
Good URL - https://www.example.com/seo/meta-tags
Bad URL - https://www.example.com/seo?=id=54321
We have covered the major SEO factors that affect the ranking of the site in the SERP and how to automate them using Behat. Hope this blog was informational!
If you'd like to automate the SEO of your site, reach out to business@qed42.com.
Happy Automation!!!

SEO services are usually expensive and hard to find since they require a considerable time and technical expertise. A handful of SEO factors can be automated with the right tools. In this blog, we will explore how to automate SEO factors using Behat.
Search Engine Optimization is the process of implementing a series of techniques on a website to improve your site’s visibility for relevant keywords on search engines.
In order to automate various SEO factors using Behat, we will be using the extension module “marcortola/behat-seo-contexts” with our additional custom contexts.
Let's understand the major SEO factors and how these can be automated.
Meta tags are the HTML tags that provide important information about the web page to the search engines. This metadata appears only in the page’s source code.
HTML Markup - <title>Drupal Development and Design </title>
Sample Scenario -
Given I am on homepage
Then the page title should be "Drupal Development and Design"
MetaContext method -
HTML Markup - <meta name="description" content="A service open source company."/>
Sample Scenario -
Given I am on homepage
Then the page meta description should be “A service open source company.”
MetaContext method -
HTML Markup - <link rel="canonical" href="http://example.com/" />
Sample Scenario -
Given I am on homepage
Then the page canonical should be “http://example.com/”
MetaContext method -
We have added below custom “AccessibilityContext” context to validate the alt text attribute, as this is not supported by the extended module.
HTML Markup - <img src="/themes/qed42/logo.svg" alt="Home" />
Sample Scenario -
Given I am on homepage
Then the images should have alt text
Accessibility Context method -
1. index - The bot will index the whole webpage
2. nofollow - The bot will NOT follow the page and any links in that webpage
3. noindex - The bot will NOT index that webpage
Note: When the robot tag is missing, crawler considers the site to be indexed and followed.
The extended module provides support for validating only index/no index values of robots tag. Therefore, we have added below custom context to validate the nofollow/follow values.
HTML Markup - <meta name="robots" content="INDEX, NOFOLLOW" />
Sample Scenario -
Given I am on homepage
Then the page should be nofollow
MetaContext method -
og:title - The title of the page/content/object as it should appear on Facebook, e.g., "QED42".
og:type - The type of the object, e.g. blog, articles. Depending on the type you specify, other properties may also be required.
og:image - An image URL which represents the object. Images must be either PNG, JPEG and GIF formats and at least 50px by 50px.
og:url - The canonical URL of the object that will be used as its permanent ID, e.g., "https://www.qed42.comwww.qed42.com".
The following properties are optional for any object and are generally recommended:
HTML Markup - <meta property="og:url" content="https://www.qed42.comwww.qed42.com" />
Sample Scenario -
Given I am on homepage
Then the Facebook Open Graph data should satisfy full requirements
SocialContext method -
Twitter:card - It describes the type of content. The card type can have one of these values - “summary”, “summary_large_image”, “app”, or “player”.
Twitter:title - Title of content
Twitter:description - The summary of the content.
Twitter:url - A canonical URL for the content
Twitter:image - A URL to a unique image representing the content of the page
HTML Markup - <meta name="twitter:url" content="https://www.qed42.com" />
Sample Scenario -
Given I am on homepage
Then the Facebook Open Graph data should satisfy full requirements
SocialContext method -
Note: Here, getOGMetaContent() method is the same as mentioned in the Open Graph Meta Tags section.
We have added below custom “UXContext” context to validate the viewport tag, as this is not supported by the extended module.
HTML Markup - <meta name="viewport" content="width=device-width, initial-scale=1">
Sample Scenario -
Given I am on "/ux/site-with-valid-viewport.html"
Then the site should be responsive
UXContext method -
Keyword optimization is the process of identifying and selecting keywords to be incorporated into a website's content, which will drive traffic from the search engines to the website. By analyzing the words searched, we can understand what the user needs.
We can achieve keyword optimization, by using keywords in - title tag, meta description, URL, links, keywords in the image alt attribute. You can refer to the Meta Tag section on how we can optimise keywords using various meta tags.
Image optimization involves two things:
A high number of images on a web page impacts page load time. And Google uses page load time as a factor for ranking. Therefore, we need to ensure the quantity of image, size of image and quality of the image added on a web page.
We have covered the SEO factors - Meta tags, Keyword, content and image optimization. Check out our next blog (Automate SEO factors testing using Behat - Part 2) in this series to discover more SEO factors like Automation to validate image optimization is covered under Page Speed SEO factor.
If you'd like to automate the SEO of your site, reach out to business@qed42.com.

Automation suites are often used to reduce manual testing efforts or to obtain testing results in less time. However, inappropriate coding practices or scripting sometimes affects the script execution performance and ultimately increases the script execution time. Many factors contribute to the automation script execution performance. One of the most notorious ones is the " hard waits " in step definitions.
Hard waits are applied to automation scripts for elements being rendered on a page. It will try to find an element for a ‘defined’ time and if within this time if the element is not found, it will throw an error. If an element is found, then it will allow you to perform further actions on it.
Let’s discuss this in more detail.
Many times, I have come across these "hard waits" being applied in step definitions. Consider the example below:
Now if there are “n” number of scenarios then the “wait” seconds keep on getting multiplied with the number of scenarios and thus increasing the script execution time.
To resolve this issue, we can write a custom function to replace the step “And I wait for n seconds” as following:
In the above custom script, we are trying to find an element first using findElement() function with certain conditions applied in the loop. Here, the script will wait for an element to load and then perform an action on it. So we don’t need to add “And I wait for n seconds” and we don’t have to worry about how many seconds it will take for an element to load.
Now our step definition will finally look like this:
And here is how we call the “findElement” function for elements before we perform any action on the respective element.
The script will keep trying to find an element and there will be a limited number of tries. After this, if an element is not found, the test suite will fail.
Do try to avoid using “hard waits” in step definitions by using the above custom function and observe the time taken for script execution. These are a few tips on how to write precise and accurate step definitions that help improve script execution performance.
If you would like QED42's help in setting up or improving your automation suites please reach out to us!
Happy Testing!

In our previous post Zephyr for JIRA: Basics, we discussed how to integrate Zephyr with JIRA and how to use it for test management. In this blog, we will explore some of the handy features of Zephyr for JIRA that facilitate efficient test management.

Using Test View, users can identify how the testing activities relate to the ongoing sprints, cycles, or stories that are a part of the given project board.
1. Allows users to see the iteration - sprints and the cycles that correspond under them with progress bars.
2. Clicking on a cycle will allow users to see test cases that are a part of that given cycle.
1. Allows users to see the flow from issue to issue - for example, an epic or a story that may relate to multiple test cases.
2. Clicking on a particular issue will show test cases that are covered by that aforesaid issue.

| This opens the Copy Teststeps pag
1. Individually - Enter the test issue's JIRA ID.
2. Via Search Filters - Enter Search Filter name and you can search for destination test issues
Zephyr imports the test cases from Excel and XML files. This feature saves the browser load time while creating test cases directly in Zephyr.
Below are the steps to import your test cases from Excel:
Note: To import the detailed test steps, we need to use ‘Zephyr for JIRA Tests Importer Utility’.



The bulk update feature saves effort and time by simultaneously updating multiple field values of selected (multiple) tests.




1. The search box allows you to enter your search queries in the new Zephyr Query Language (ZQL).
2. ZQL is a simple structured query language that allows you to string together the right fields to search with values, using the appropriate operators and keywords.
For example, project = ABC AND executedStatus = FAIL

Consider, you are using continuous integration (CI) framework for automation. And you want to integrate it with ‘Zephyr for JIRA’, such that whenever test cases are executed in the CI framework, the test execution status is updated for the mapped tests in Zephyr.
Zephyr for JIRA provides you with this feature as part of ZAPI (or Zephyr API). ZAPI is an API that can be integrated with CI framework to update testing information in ‘Zephyr for Jira’ programmatically.
There are integrations available between Zephyr for Jira and the popular continuous integration tools
Assuming, there is an existing JIRA project and Zephyr is installed and configured.

Click on Zephyr
Navigate to the Automation section and click on API Keys option.
Click on the Generate button
Copy both the access and secret key.


1. Create a project
2. Add a test cycle
3. Add test scripts to the created test cycle
1. Project details
2. Version ID
3. Test cycles and Test cases
Zephyr provides a suite of tools to optimize speed and quality of software testing, empowering us with the flexibility and visibility you need to achieve agility.

Test management is the process of taking a project's requirements, building a test plan, writing the tests, planning the test activities and capturing the results. Test management tools that provide these capabilities, ease the testing process drastically. One such test management tool is Zephyr for JIRA.
Zephyr is an integrated plugin which provides the test management capabilities for projects in JIRA. Let's discover Zephyr for JIRA (cloud version) as a test management tool.
First, we need to install Zephyr for JIRA plugin and then add the issue type ‘test’ to the project.

A test cycle is a container for test cases. It allows the test cases to be grouped logically and executed in a structured fashion.
First, we need to create a test cycle using below steps:

A test case is a set of actions executed to verify a particular feature or functionality of the software application. To create a test case in Zephyr, first, we need to create an issue with type ‘Test’ and then add test steps to it.
Step 1: Creating a Test
Test Summary - Title of the test cases. Mandatory field.
Test Description - Description of the test case
Components - Select component specific to the project or feature
Fix Version - Select fix version/Release of the project
Priority - Select the priority of the test case
Assign To - Name of the user responsible for executing the test cases
Sprint - Sprint of the test case
Epic Link/Story links - Epic/Story ID for which test cases is been created
Attachments - Attach evidence/reference document
Step 2: Adding test steps to the Test
Edit - Click on the cell - Modify - Click outside the cell
Clone - Click on the ‘Clone’ button available under the ‘Actions’ column
Delete - Click on ‘Delete’ button available under ‘Actions’ column

We can add tests to test cycle in two ways:
Individually - Using Test ID
Via Search Filter - Using existing Search Filter
Another Cycle - Using Another test cycle

Test Execution is the process of executing the test cases in a test cycle and comparing the expected and actual results. After adding tests to the test cycle, we need to execute them. We can execute the test in Zephyr using either of the below ways:

4. Raising and Linking Bug
Summary - Title of the bug
Reporter - User reporting the bug/issue
Description - Description of the bug (Steps to reproduce, Actual/Expected result)
Priority - Select Priority of the bug to get fixed
Linked Issues - Select test/issues related to this bug
Assign To - Select user who will work to fix this issue


There are several ways to track testing progress in Zephyr.
The ‘Test Summary’ page gives an organized view of all the tests for a particular project, broken down by Versions, Components, and Labels.
Traceability matrix provides the ability to map requirements to defects or vice-versa. Zephyr provides two traceability matrices:
1. Requirements to Defects: Generates full traceability report from Requirements - Tests - Test Executions - Defects.
2. Defects to Requirements: Generates full traceability report from Defects - Test Executions - Tests - Requirements.

Zephyr automatically tracks below test metrics for the project/version:



Pros:
Cons:
Thanks for reading! Hope this gives you an overview of how to integrate Zephyr with JIRA and use test management capabilities in any JIRA project. Part 2 of this blog series Zephyr for JIRA: Features explores some quick and handy features of Zephyr. Stay tuned!

The e-commerce wave of conducting business online is growing day by day. And with that, delivering the best user experience is their utmost priority. Our team recently developed a Decoupled e-commerce site - 'Shop the Area' powered by Drupal as its backend and Gatsby as frontend. The website carries several independent boutiques. The user can buy products from the boutiques which are within their 15-mile radius. Since an e-commerce site demands numerous functional and end to end tests, automating this was cumbersome. So, we decided to implement Cypress for automating the testing process for our e-commerce site.
Cypress is an end to end JS-based web-testing framework which is an excellent tool for an end to end testing, resulting in easy implementation of Functional test scenarios in websites. Cypress is easy to understand and adopt. It has an awesome GUI, runs on the browser, Automatic waits, fast response, easy debugging etc.
I installed Cypress using npm, the npm must be pre-installed in the system. Then, create a project folder, set this folder as the root folder in the terminal and install Cypress using the code given below.
1. Download Cypress
2. Mention base URL pointing at the domain which we are going to test in cypress.json file. Since we are referring to ‘Shop the area’ website, I will enter “https://shopthearea.netlify.app/”. We can also set viewport in which we want to test.
3. So let's try out a simple test script. Create a .js file in the integration folder Write a scenario that needs to be tested.
For example in our site, I create header.js script to check the menu link and their landing page in the header.
Spec file: Header.js
Since I have implemented POM in my tests, I have created a function for pointing on to the menu and a JSON file for storing user data like the URLs for this test.
Let’s import these 2 files in the test file.
POM file: header.js
Data file: header.json
4. Open the GUI through the terminal.
5. Run test
.gif)
Organising the Test folder is essential for easy maintenance.
To understand the structure to the image below.

Functional testing can be done for the following using Cypress:
Test scenarios example:
Since this website has a location feature, the script includes setting location before each test section.
Spec File: Cart.js
POM file:cart.js
.gif)
Example Scenarios:
Spec File: search.js

In the first scenario, the search term display in the search field of the result page failed, this is clearly highlighted in the Cypress test runs. This feature is helpful in debugging such issues.
Cypress test runner is fast and easy to write-run end-to-end tests. Cypress has numerous plus points like easy debugging, simple cypress GUI, automatic waits, supports different browsers, saves screenshots and videos, consistent tests, etc. All these features make it a user-friendly testing tool.
Few points to be kept in mind while automating an e-commerce website:
Happy Testing :)

It is always a challenging part to decide which type of testing is to be done at the end of a sprint or at the end of a project. Mostly it’s being misunderstood and we often end up using the wrong one or we don’t follow the right naming convention for the testing that we usually do.
For example, on some of the projects, we spend a day or two to perform entire application testing at the end of the sprint. And we label it as Smoke testing. This is not right! This should be identified as Regression testing.
At the end of the sprint, we should mostly perform Smoke/Sanity testing based upon the deadline.
If you don’t have enough time to opt for Smoke testing or else perform the sanity checks. When you have an ample amount of time in your hands, Regression testing is the last option.
So the preferences should be like Smoke testing, Sanity testing, and then Regression testing as per the project deadline.
Consider an example for this, suppose we have 50 functional components. Out of them, 10 are major components and let’s say remaining components revolve around them.
Then as a part of Smoke Testing, we should quickly verify the major 10 components.
As a part of Sanity testing, we should verify all the components.
And in Regression testing, we should verify the complete system (all components) and bugs too.
Based on the selected testing approach share an ETA with the respective Project Managers or Leads and get it approved
Depending upon the above example, QAs should be ready with the following documentation for each testing phase:
We should document all results of these testing for future references. For documenting the results we should use a Spreadsheet or any other test case management tool.
Tracking the results is the most important part of Smoke, Sanity, and Regression testing. After testing, we should analyze the present result with the previous results. This helps us in understanding the root cause of the issues occurring and tracking issues in an easier way.
We should always try to understand the difference and importance of all these three types of testing and try to explain the same to other project members so that we can collaboratively build a good process around implementing each one of this on the project.
.avif)
Often Quality Assurance Engineers focus only on the testing responsibilities assigned to them. And that’s what our job profile is, after all. However, to excel at our jobs we need to walk the extra mile. We need to go beyond just writing test cases and scenarios. We need to take ownership of the project!
Advantages of doing so:
Happy Testing!

Our job as Quality Assurance engineers is to test websites and applications before they are delivered, improving the user experience for a seamless experience across all platforms. It is imperative that the quality assurance and testing services blend seamlessly into the development life cycle delivering error-free and high performing web, cloud, and mobile apps.
Previously I have been sharing some QA tips that will make your work better, faster and easier. This time, I would like to answer a couple of questions that every QA might come across in their careers:
In my opinion, as a QA one should have:
Let's go through different basic strategies which will help you achieve this:
Many a time I come across people with queries such as:
Well, in my opinion, it's not too late to start now! It's not that difficult to start working on automating your use cases or scenarios.
Ask your current organisation to make you part of an automation project. If this is not possible you can do the following things:
Happy Testing :)

Before we delve deeper in the how’s and why’s let us understand what Data-Driven Analytics reports are?
This will help in planning the testing activities where QAs will have a clear understanding of:
1. Will be useful only when the 1st version is released in the market. Analytical data will be generated only when the web application is live.
2. Setting up analytics tool for project and it's licensing.
Setting up Google Analytics for a project and analyzing the reports generated and then based on it updating the test activities.
Therefore, it is very important to understand 'What' and 'How' your users are doing on your website.
Happy Testing!