Quality Engineer vs Automation Engineer vs SDETs

What is Quality Engineer ? here is CSQE definition:

The Certified Software Quality Engineer understands software quality development and implementation, software inspection, testing, verification and validation, and implements software development and maintenance processes and methods.

What Are the Core Competencies of a CSQE?

  • Enhanced fundamental understanding of quality philosophies, principles, methods, tools, standards, organizational and team dynamics, interpersonal relationships, professional ethics, and legal and regulatory requirements.
  • Thorough understanding of systems architecture and how to implement software development and maintenance processes to reduce the risks associated with various software development methodologies.
  • Define, select, and apply product and process metrics and analytical techniques, and have a sound understanding of measurement theory and how to communicate results.
  • In-depth understanding of verification and validation processes, including early software defect detection and removal, inspection, and testing methods.
  • Advanced knowledge of configuration management processes, including planning,
    configuration identification, configuration control, change management, status accounting, auditing, and reporting.



Reference links:







Some companies usually interchange the term QA and QC, so many people think QA and QC are same and interchangeable but this is not true.
Both are tightly linked and sometimes it is very difficult to identify the differences.
Fact is both are related to each other but they are different in origins.

In my current project, QA is acting like Process QA. My role is automation QC, it is like Software QA which aims to identify and fix defects.

Typically , PQA will work with the whole software development team and audit how the team followed the process every sprint (2 weeks per sprint) , some specific projects will be audited quarterly.

Quality Assurance vs Quality Control

Quality Assurance Quality Control
It is a process which deliberate on providing assurance that quality request will be achieved. QC is a process which deliberates on fulfilling the quality request.
A QA aim is to prevent the defect. A QC aim is to identify and improve the defects.
QA is the technique of managing the quality. QC is method to verify the quality.
QA does not involve executing the program. QC always involves executing the program.
All team members are responsible for QA. Testing team is responsible for QC.
QA e.g. Verification. QC e.g. Validation.
QA means Planning for doing a process. QC Means Action for executing the planned process.
Statistical Technique used on QA is known as Statistical Process Control (SPC.) Statistical Technique used on QC is known as Statistical Quality Control (SPC.)
QA makes sure you are doing the right things. QC makes sure the results of what you’ve done are what you expected.
QA Defines standards and methodologies to followed in order to meet the customer requirements. QC ensures that the standards are followed while working on the product.
QA is the process to create the deliverables. QC is the process to verify that deliverables.
QA is responsible for full software development life cycle. QC is responsible for software testing life cycle.

Key Points

  • In QA, processes are planned to evade the defects.
  • QC agreements with discovery the defects and modifying them while making the product.
  • QA detects weakness.
  • QC detects defects.
  • QA is process oriented
  • QC is product oriented.
  • QA is failure prevention system.
  • QC is failure detection system.

Reference links:




Common GIT scenarios in my project

There are three main sections of a Git project: the Git directory, the working tree, and the staging area.

The Git directory is where Git stores the metadata and object database for your project. it is what is copied when you clone a repository.

The working tree is a single checkout of one version of the project. These files are pulled out of the compressed database in the Git directory and placed on disk for you to use or modify. It is your scratch space, used to easily modify file content.

The staging area is a file, generally contained in your Git directory, that stores information about what will go into your next commit. Its technical name in Git parlance is the “index”, but the phrase “staging area” works just as well.

The Three States in Git : modified(deleted), staged and committed.

The HEAD in Git is the pointer to the current branch reference, which is in turn a pointer to the last commit you made or the last commit that was checked out into your working directory. That also means it will be the parent of the next commit you do. It’s generally simplest to think of it as HEAD is the snapshot of your last commit.

The Index is your proposed next commit. Git populates it with a list of all the file contents that were last checked out into your working directory and what they looked like when they were originally checked out. It’s not technically a tree structure, it’s a flattened manifest, but for our purposes it’s close enough. When you run git commit, that command only looks at your Index by default, not at anything in your working directory. So, it’s simplest to think of it as the Index is the snapshot of your next commit.


Scenario: you pushed a commit to remote repository (eg: github) with your credential
but you see someone else name instead of your name.
reason:  Git always takes the name and email in git config –global when pushing a commit , no matter what credential you entered.

$ git config --list
user.name=Thach Hoang

how to config this:

git config --global user.email "email@example.com"
git config --global user.name "Thach HOang"

Scenario: you want to download a repository in local , so that you can work on it.

git clone https://github.com/libgit2/libgit2

Scenario:  add one file , modify one file , remove one file, then commit and push to remote repo

$ git status
 Changes not staged for commit:
    modified: README.md
    deleted: oldfile.md
 Untracked files:
$ git add README.md
$ git rm oldfile.md
$ git add newfile.txt

$ git commit -m "First commit"
$ git push origin master  (git push  )

Scenario:  you already have a commit. now you find out that  you missed something and need to add it into that commit.

how:  update what you want and create new commit with option –amend. it will replace previous commit:

$git commit --amend -m "This is new commit that will replace old one"

Scenario: you modified and messed up a file but not yet in stage. you want to revert it back to original.

git checkout README.txt

Scenario: you already added/removed wrong file into stage. now you want to unstage it , you don’t want that file in the next commit.

git reset HEAD README.txt

Scenario: you already committed the change. now you want to undo the committed and leave file change in the stage(INDEX).

git reset --soft HEAD^

Scenario: Compare modified files
(feature-1100)$git diff develop

Create a branch

git checkout -b 

Scenario:  Update the branch and resolve conflict if any using rebase.

(feature-1100)$git checkout develop 
(develop)$git pull
(develop)$gc feature_1100
(feature-1100)$git rebase develop
resolve conflict then continue the rebase process:
(feature-1100)$git rebase --continue

Scenario:  Squash N last commits into one commit. It make resolving conflict easier.

git rebase --interactive --autosquash HEAD~N


Scenario: you are working on branch feature-A with changes. Now you need to switch to branch feature-B to do something urgent. git stash help you store the change of feature A and allow you to switch to another branch. you can return to branch feature-A and restore the changes from stash.

Put in stash:

git stash save "Message"

Show stash:

git stash list

Show stash stats:

git stash show stash@{0}

Show stash changes:

git stash show -p stash@{0}

Use custom stash item and drop it:

git stash pop stash@{0}

Use custom stash item and do not drop it:

git stash apply stash@{0}

Delete custom stash item:

git stash drop stash@{0}

Delete complete stash:

git stash clear

…to be update…

Reference links:







Common Basic and Advanced Xpath/CSS Selectors

Here are the list of common basic to advanced selectors which I usually use in my test code:

I. Basic

A direct child in XPATH is defined by the use of a “/“, while on CSS, it’s defined using “>”
Eg: xpath= //div/a ; css= div > a
Note: Single slash ‘/’ anywhere in xpath signifies to look for the element immediately inside the parent element.
Double slash ‘//’ signifies to look for any child or nestedchild element inside the parent element.

If an element could be inside another or one it’s childs, it’s defined in XPATH using “//” and in CSS just by a whitespace.
Eg: xpath= //div//a ; css= div a

3. ID
An element’s id in XPATH is defined using: “[@id=’example’]” and in CSS using: “#”
Eg: xpath = //div[@id=’example’]//a ; css= div#example a

For class, things are pretty similar in XPATH: “[@class=’example’]” while in CSS it’s just “.”
Eg: xpath= //div[@class=’example’]//a ; css=div.example a

II: Advanced

This is useful for navigating lists of elements, such as forms or ul items.
The next sibling will tell selenium to find the next adjacent element on the page that’s inside the same parent.
Let’s show an example using a form to select the field after username.
css=form input.username + input

If you don’t care about the ordering of child elements, you can use an attribute selector in selenium to choose elements based on any attribute value.
A good example would be choosing the ‘username’ element of the form without adding a class.
css=form input[name=’username’]

We can even chain filters to be more specific with our selections.

CSS selectors in Selenium allow us to navigate lists with more finess that the above methods.
If we have a ul and we want to select its fourth li element without regard to any other elements, we should use nth-child or nth-of-type.

If we want to select the fourth li element (Goat) in this list, we can use the nth-of-type, which will find the fourth li in the list.
css=ul#recordlist li:nth-of-type(4)

On the other hand, if we want to get the fourth element only if it is a li element, we can use a filtered nth-child which will select (Car) in this case.
css=ul#recordlist li:nth-child(4)

Note, if you don’t specify a child type for nth-child it will allow you to select the fourth child without regard to type.
This may be useful in testing css layout in selenium.
css=ul#recordlist *:nth-child(4)

CSS in Selenium has an interesting feature of allowing partial string matches using ^=, $=, or *=. I’ll define them, then show an example of each:

^= Match a prefix
=> A link with an “id” that starts with the text “id_prefix_”

$= Match a suffix
=> A link with an “id” that ends with the text “_id_sufix”

*= Match a substring
=> A link with an “id” that contains the text “id_pattern”

//div[@class=’homepage-hero’]//a[text()=’Enroll now’]

Syntax: //tag[contains(attribute, ‘value’)]
//div[@id=’navbar’]//a[contains(@class,’navbar-link’) and contains(@href,’sign_in’)]

Syntax: xpath-to-some-element//parent::<tag>

8. XPATH – Preceding Sibling
Syntax: xpath-to-some-element//preceding-sibling::<tag>

9. XPATH – Following Sibling
Syntax: xpath-to-some-element//following-sibling::<tag>


[ERROR] COMPILATION ERROR when running maven test

Problem: Error below is shown during run maven test:

[INFO] -------------------------------------------------------------
[ERROR] No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.424s
[INFO] Finished at: Tue Oct 29 15:21:01 IST 2013
[INFO] Final Memory: 5M/15M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler- plugin:3.1:compile (default-compile) on project TEST-WEB: Compilation failure
[ERROR] No compiler is provided in this environment. Perhaps you are running on a JRE rather than a JDK?


On your Eclipse IDE, go into Window > Preferences > Java > Installed JREs > and check your installed JREs. You should have an entry with a JDK there.


Control Panel > Java > Java Control Panel > Java > View > change to jdk.

Then Right-Click on your Project -> Maven -> Update Project


Generate/search cssSelector and Xpath on Firefox 55 onward

As you know, Firebug extension is no long working on Firefox 55 and later. The latest version of Firebug is 2.0.19 which compatible with Firefox 30 – 54. So you may want to install the old Firefox build 54 , disable auto update and happy with the latest Firebug.

But it is quite inconvenience. So I will share you 2 tools that we can do the same functionalities of Fire Bug such as : inspect Element, generate css Selector or xpath of element, search an element using css/xpath…

The first tool is Firefox DevTools .This is the tool suggested by http://www.getfirebug.com .

“The Firebug extension isn’t being developed or maintained any longer. We invite you to use the Firefox DevTools instead, which ship with Firebug.next”

generate locator

How to use Firefox Developer tool:

  • Press F12 or right click on element and select “Inspect Element”.
  • Click icon pickE  to pick an element from the page. Then you can right click on Element in Inspector tab and select Copy (CSS Selector, XPath ) as you see in the screenshot above. however the XPath generated here is absolute XPath . so it is not useful for me.
  • Search Element using css selector: Firefox Dev tool only allows us to search an element using CSS Selector. searching an Element using XPath is not supported yet. There is an enhancement S2 for this Bug 963933 . I hope they will add this feature soon.

XPath locator is very important for us. It is quite handy to handle some elements which there is no ID and cssselector cannot help. you have to do an XPath search, then walk up the DOM, then back down to get to the element you want.

Fortunately , there is another extension on Firefox can help us to generate and search xpath locator. It is AutoPager.

(this add-on also help to generate xpath: https://addons.mozilla.org/en-us/firefox/addon/element-locator-for-webdriv/)


How to use AutoPager Extension:

  • Generate xpath of Element: right click on Element on the web page, select Auto Pager >XPath Utils > Create xpath. It will show the AutoPager window. you can get the xpath in Link XPath field. It also have a list of possible xpath and the number of match found. Make sure you select the one which have only one match found for your testing. You also can click on find button pick and pick an element on web page to generate xpath for it.
  • Search xpath:  This is the feature that i use frequently . it is very handy. You can define your own xpath and paste it into Link XPath and enter to check if there is any element match with your defined xpath. Click … on the right of Link Xpath field, it will show you all functions used to define an xpath. I love it.  When you search xpath , make sure you are on the correct Frame.


XPath Utils
generate xpath of element
Generate an Xpath for Element
XPath Expression
XPath Expression: help us to define Xpath

Handle Native Windows upload popup using Robot and Clipboard class

When we click on upload button on a web page, an native windows popup will be displayed and we need to give the path to the file we want to upload. Selenium WebDriver cannot handle this popup.

There are two solutions for this scenario.

  1. Using Java Robot and Clipboard classes to simulate copy and paste action. we can paste the file path in the popup window and simulate enter key event.
  2. Using AutoIT tool to handle the pop up.

In this post, I will show you how to handle windows upload popup using the first solution.

1. import these class into your test script:

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.datatransfer.StringSelection;
import java.awt.event.KeyEvent;

2. Create instance of Robot class and Clipboard class
Robot robot = new Robot();
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();

3. use StringSelection to cache the upload file path string.

StringSelection filepath = new StringSelection(“F:\\DOCUMENT\\SELENIUM\\myCV.doc”);

4. Copy the file path to Clipboard

clipboard.setContents(filepath , null);

5. Use Robot class to simulate CTRL+C and CTRL+V key events :


below is full script to send an email with attachment:


package mypacket;

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.datatransfer.StringSelection;
import java.awt.event.KeyEvent;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import java.awt.Toolkit;

public class SendGmailwithRobot {
 WebDriver driver;
 String baseURL;

 public void beforeTest() {
 System.setProperty("webdriver.gecko.driver", "F:\\SOFTWARE\\Automation\\geckodriver.exe");
 baseURL = "https://www.google.com/gmail/about/";
 driver = new FirefoxDriver();
 driver.manage().timeouts().implicitlyWait(40, TimeUnit.SECONDS);

 public void sendGmail() throws InterruptedException, AWTException {
 driver.findElement(By.linkText("Sign In")).click();
 driver.findElement(By.id("password")).sendKeys("your gmail password");
 driver.findElement(By.xpath("//div[@class='wO nr l1']//textarea")).sendKeys("destinationemail@gmail.com");
 driver.findElement(By.xpath("//input[@name='subjectbox']")).sendKeys("email title here");
 WebElement attachbt = driver.findElement(By.xpath("//div[@class='a1 aaA aMZ']"));

Robot robot = new Robot();
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection filepath = new StringSelection("F:\\DOCUMENT\\SELENIUM\\myCV.doc");
clipboard .setContents(filepath, null);



 public void afterTest() {


Linux tips for Automation

1. How to Keep Your SSH Sessions Alive

Login as root and change two settings below:

$vi /etc/ssh/sshd_config
ClientAliveInterval 0
#ClientAliveCountMax 3

number of seconds that the server will wait before sending a null packet to the client (to keep the connection alive). This is the limit of how long a client are allowed to stay unresponsive before being disconnected. Setting a value of 0 (the default) will disable these features so your connection could not be dropped if it is idle too long.

Sets the number of server alive messages (see below) which may be sent without ssh(1) receiving any messages back from the server. If this threshold is reached while server alive messages are being sent, ssh will disconnect from the server, terminating the session.
you can run $man sshd_config to read more details about these settings.

Another example:
ClientAliveInterval 300
ClientAliveCountMax 2

These settings will make the SSH client or server send a null packet to the other side every 300 seconds (5 minutes), and give up if it doesn’t receive any response after 2 tries, at which point the connection is likely to have been discarded anyway.


2. Running  a command with sudo without entering password.

[admin@Thachsystem ]$ sudo /usr/share/hnthach/install_build.sh

for example, i want to run the script above in admin user. There are some commands in that script required sudo. So to run it , I need to do the following steps:

– Create the file installation in  /etc/sudoers.d/ directory.

–  Add one line to installation file:

[admin@Thachsystem ]$ sudo visudo -f /etc/sudoers.d/installation
%admingrp ALL=(ALL) NOPASSWD:/usr/share/hnthach/install_build.sh

the syntax is:  %groupname host = (user privileges ) NOPASSWD: /sbin/shutdown

admingrp is group name, this means that all member of the admingrp group will run this command using sudo without a password.

You can also use /etc/sudoers  instead of modifying /etc/sudoers.d. But i would prefer sudoers.d.  This is good way to separate customized changes to sudo rights and leaves the original sudoers file untouched.




Jmeter – Share cookie across thread groups

Objectives:  Get cookie data from the request in first thread group, store it to csv file. so requests in other thread groups can use that cookie.


  • Create new csv file. It needs to be clean up before running test suite.
  • Extract cookie data from thread group , save it as variables and store them to csv file.
  • In other thread group, fetch data from csv file and save them as variables. Then Insert cookie to the request.


  1. create new csv file:

Manually create a new csv file. Eg : D:\DailyRun\Jmeter\cookievar.csv

  1. Clean up csv file before getting and writing cookie into it. Otherwise, multiple values will append to csv file and it causes wrong cookie inserted to requests in other groups.

Use BSF Sampler to execute the command: 

exec(“cmd.exe /C D:\\thachhoangngoc\\deleteCSV.bat”);

This bat file contains commands to copy fresh file and overwrite the old one.

echo Delete cookievar.csv

copy /Y D:\thachhoangngoc\cookievar.csv D:\DailyRun\Jmeter\cookievar.csv

(Actually, this is a work around. I couldn’t find a solution to clean up csv file directly in Jmeter. I tried method  file.clear() in Beanshell script but it didn’t work.)BSF Sampler

  1. extract cookie data from first request. cookie will be generated in first request. You can find cookie data in response header.

Use Regular Expression Extractor to extract cookie data and save it to variables. In this example, cookie data contains JSESSIONID and JSESSIONIDSSO. So I added two regular expression Extractor.Regular Expression Extractor1Regular Expression Extractor2

  1. write two cookie variables to csv file.

Use BeanShell PostProcessor. File path here is D:\DailyRun\Jmeter\cookievar.csv.beanshellPostProcessor

  1. fetch cookie data from csv file in other thread groups:CSV data set config

Insert cookie into request using  BeanShell PreProcessor.

 InsertCookieusing BeanshellPreProcessorTestPlanJMX