

Have you ever experienced when your team made a small change, and chaos resulted in production? You look through your logs, and your unit tests are all passing, but your real users are hitting a dead end. That feared feeling, that moment you realize your QA process is based on hope, not evidence. This is the type of problem we need to solve.
The reality is that relying on manual QA is not a good choice. But what if you could take the guesswork out of it? What if every single code change, feature addition, or bug fix was validated before your developers could merge? There is a difference when combining automatic test automation with GitHub Actions. And when you can amplify that with QA.tech’s AI-powered testing, you have a strong, reliable pipeline with detection of issues sooner and with limitless scale.
In this guide, I’ll walk you through how to set up your first automated workflow and extend it to make a robust test automation with QA.tech, and leave you with a set of great best practices along the way.
For QA professionals, GitHub Actions is transformative because it offers you a single, centralized and dynamic repository for continuous quality assurance right next to your code (you don't need any other CI/CD tool set!). It also delivers great benefits to your pipeline:
main branch remains healthy and stable.If you’re already familiar with GitHub Actions, here’s the core workflow structure you will be using. This basic pattern is the foundation for all test automation:
# The fastest way to run your tests in CI
name: Quick Test Run
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '18'
- run: npm ci
- run: npm testYou can now skip ahead to the Integrating with QA.tech for AI-Powered Testing section to see how we build upon this foundation.
To get started, you’ll need some knowledge on how to use GitHub, alongside the access to GitHub repository where you can add files. You should also have a basic understanding of GitHub Actions components:
push, pull_request, or schedule.Let's kick things off by creating a simple test automation workflow.
Step 1: Clone the sample demo app.
We'll use a basic Node.js app in this example. If you want to follow along, you can clone our demo project.
git clone https://github.com/tarunsinghofficial/demo-reg-form.git
cd demo-reg-formRun the app.
npm install
npm startVisit http://localhost:3000 to see the registration form in action. Try registering a user and testing the validation (this is exactly what QA.tech's AI will learn to test automatically).
Step 2: Create a GitHub Actions workflow.
As we have seen earlier, a GitHub Actions workflow is defined in a YAML file. Inside your cloned project, create a .github/workflows directory and add a new file named test.yml:
# .github/workflows/test.yml
name: Node.js CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm testLet’s break down this code:
name: This is the name of your workflow.on: This is the event that triggers the workflow. For now, we’ve configured it to run on push and pull_request events on the main branch.jobs: Here’s the heart of the workflow. In our example, we define a single job named build.runs-on: This specifies the runner (the virtual machine where the job will execute). For the majority of use cases, ubuntu-latest is a great choice, as it’s a common Linux environment.steps: Next, we’ve got the sequential list of actions the job will take.actions/checkout@v4: This is a pre-built action that checks out your repository's code so that your workflow can access it.actions/setup-node@v4: This is another powerful action that sets up a Node.js environment on the runner. We're specifying version 18.npm ci: This command installs our project dependencies. We use npm ci (clean install) instead of npm install because it's specifically designed for automated environments, ensuring consistent builds.npm test: This is the command to run our test suite, which is defined in the package.json file.After you've created and committed this file, push your changes to your GitHub repository. The workflow will automatically trigger, and you'll be able to see the results under the "Actions" tab of the repository.
The on section of the workflow determines when tests execute. You can follow the common strategies mentioned below:
# Strategy 1: Run on every push and PR (best for small teams)
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
# Strategy 2: Only on PRs (saves CI resources)
on:
pull_request:
branches: [ "main" ]
# Strategy 3: Conditional on file changes (best for larger projects)
on:
push:
branches: [ "main" ]
paths:
- 'src/**'
- 'tests/**'
pull_request:
branches: [ "main" ]
paths:
- 'src/**'
- 'tests/**'Choosing the right testing strategy depends on your team size and project needs. Running tests on every push or PR is ideal for small teams, as it ensures continuous feedback without overwhelming your resources. On the other hand, opting to run tests on PR only results in less CI usage.
For larger projects, a path-based strategy can be especially efficient, as it runs tests only when relevant files change.
The core issue with traditional test scripts is that they're fragile.
Let’s say you’ve put hours into writing a test that opens a form, fills it out, clicks "Submit", and verifies that the success message is there. Then, a designer changes the button text from "Submit" to "Register"; all of a sudden, the test breaks. Or, even worse, the test might still pass as long as the underlying HTML structure remains the same, even though the actual functionality is broken.
QA.tech solves all of this by understanding your application the same way a human user would. Instead of relying on hard-coded selectors, exact text, and similar, our AI observes user workflows, learns what that behavior looks like in your application, and creates tests that focus on functionality, not the implementation detail.
Now, we’ll focus on our user registration demo application to see how QA.tech‘s approach is fundamentally different.
Step 1: Get your secret credentials.
To integrate QA.tech into your workflow, you need two values:
QATECH_API_TOKEN : Your QA.tech API tokenQATECH_PROJECT_ID : Your QA.tech project IDSimply sign up for QA.tech and create a new project. During the setup process, you may be asked to provide a test site URL; you can use your own deployed app (the one you’ve just cloned and deployed to any free web service provider like Render.com, etc.) or, this URL for demo purposes.

Once you’re done, you’ll find secret credentials in your project settings.

Warning: Never hard-code these values directly into your YAML file! Store them as GitHub Secrets instead. Here’s how you can do this:
Settings > Secrets and variables > ActionsQATECH_API_TOKEN and QATECH_PROJECT_ID .
Step 2: Set up your workflow.
Now, let’s create our QA.tech workflow within the project.
Create a new file in the directory as .github/workflows/qa-test.yml, and add the YAML code mentioned below. This is the complete file that brings together both your unit tests and the QA.tech integration.
# .github/workflows/qa-test.yml
name: QA.tech AI Testing
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
# Run unit tests first
unit-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "18"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Run unit tests
run: npm test
# Run QA.tech AI tests on your deployed app
qa-integration-tests:
runs-on: ubuntu-latest
needs: unit-tests
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run QA.tech AI tests
uses: QAdottech/run-action@v2
with:
api_token: ${{ secrets.QATECH_API_TOKEN }}
project_id: ${{ secrets.QATECH_PROJECT_ID }}
blocking: true
test_plan_short_id: "add_your_test_plan_id"
applications_config: |
{
"applications": [
{
"name": "default",
"url": "https://demo-reg-form.onrender.com" // or add your deployment url for testing
}
]
}
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: qa-tech-results
path: |
qa-tech-results.json
screenshots/
retention-days: 30Let’s break down this workflow into two distinct jobs:
needs: unit-tests line? This is a crucial dependency. It means this job will only run if the unit-tests job is successful. This is a great practice for CI/CD, as it prevents you from wasting your time running full-blown integration tests on broken code.The Run QA.tech AI tests step is where we call QA.tech into action. We pass our secrets, set blocking: true (which tells the workflow to wait for test results), and provide our test_plan_short_id and applications_config. The applications_config is a JSON object that tells QA.tech where to find your application so that it knows what URL to test.
Step 3: Run and view your tests.
Now, simply push your updated qa-test.yml file to the GitHub repository. You will see the workflow automatically kick off.
You can monitor the progress directly in your GitHub repository under the "Actions" tab. Here, you'll see both the unit-tests and qa-integration-tests jobs running.

As the QA.tech tests start, you'll also notice a direct link in the logs that takes you straight to the test run on your QA.tech dashboard.
Click on that link, and you can watch as QA.tech navigates your application and executes the tests you've created in real time. When the job is complete, the status in GitHub Actions will update, and you'll get a clear pass/fail result. You can also view the detailed report, including screenshots and logs, right from the dashboard.

Once you’ve had your basic workflow done, you can start leveraging more advanced patterns for building a robust testing pipeline.
At some point, you may want to avoid running jobs that aren’t required and may prefer a workflow to run only when a specified condition is met. In such cases, you can use the conditions to control job execution. For example, you might only want to run your test suite on the pull_request and branch being merged events:
on:
pull_request:
branches: [ "main" ]
jobs:
e2e_tests:
if: github.event_name == 'pull_request' && github.event.pull_request.head.ref != 'main'
runs-on: ubuntu-latest
steps:
# ... your e2e test stepsNow, the if condition ensures the job only runs if the event is a pull_request , and the branch being merged isn't main itself. This way, redundant runs are prevented.
As your test suite expands, you may want to try running tests in parallel to save time. However, without the proper tools, things can get pretty complicated. You’ll need to separate your test into test files manually, create multiple parallel jobs, and figure out how to manage test runners and combine the results. This often results in flaky, hard-to-maintain pipelines.
That’s where QA.tech steps in. You don't have to manually split your test suite or configure complex matrix jobs in GitHub Actions. The QAdottech/run-action does the heavy lifting for you and distributes the test workload across multiple runners on our end. So, you get the benefits of parallel testing, such as faster feedback and more efficient use of your CI minutes, without the added complexity of managing it yourself.
Here are some top practices you should follow to get the most out of GitHub Actions:
unit-tests.yml is great for fast, lightweight checks, whereas e2e-tests.yml is a good choice for more extensive, slower tests that might run on specific branches or on a schedule.actions/cache action can cache your node_modules directory so that you don't have to reinstall everything each time.GitHub Actions can help you go from a simple npm test command to a full-fledged, AI-powered test automation pipeline. By integrating QA.tech, you will move past the limitations of manual scripts and brittle selectors and adopt a more intelligent and resilient approach to quality assurance. At the same time, your team will benefit from faster feedback and reduced burden of test maintenance.
Ready to transform your QA process and boost your development speed? Start your free trial today and connect your GitHub repository to see the power of AI testing in action.
Stay in touch for developer articles, AI news, release notes, and behind-the-scenes stories.