Foreword There is often the need to check whether your production system is working as expected. This is where sanity checks are coming to be useful. We will be implementing the project via serverless architecture in the AWS cloud leveraging platform. A year ago I've written an article about testing. And it used to be the best tool for testing, in my opinion. jest-puppeteer But today I'm glad to announce that its ancestor completed the maturation process and is ready to jump into your production codebases. Let's welcome Playwright! Puppeteer vs Playwright comparison The essential difference is that puppeteer was coined as an automation framework and playwright as the testing framework. Other discrepancies are growing from this fact. Moreover, . I'm convinced that they have a ton of relevant experience and will avoid all the challenges they faced with Puppeteer. Playwright is designed by the same core developers who did Puppeteer What did Playwright bring to the testing realm? 1. Playwright covers all three modern browser engines so you write your tests once and they will be run in different browsers. 2. Playwright now has its own test runner. You don't need to use jest or smth of a kind. 3. Built-in screenshot capturing and video recording. 4. Overall it's way more stable and usable. 5. Playwright community is great. I've reported several bugs and they all were fixed really quick. Let's create our Playwright project Firstly we need to create our file. package.json { : , : , } "name" "playwright_tests" "version" "1.0.0" Then we need to install browser engines and playwright itself. npm i @playwright/test --save # install supported browsers npx playwright install As a sidenote, you can install only browser's engines that you need. Or even install custom ones. Now let's create our folder and put there. File should have in its name to be discovered by the test runner. tests first.test.js .test.js tests/first.test.js { test, expect } = ( ); test( , ({ page }) => { page.goto( ); page.click( ); expect(page).toHaveURL( , ) expect(page).toHaveTitle( , ) }); const require '@playwright/test' 'top story navigation' async await 'https://hackernoon.com/' // search for "Top Stories" text then filter down to visible await 'text=Top Stories >> visible=true' await 'https://hackernoon.com/tagged/hackernoon-top-story' await "#hackernoon-top-story stories | Hacker Noon" Code is simple and mostly self-descriptive. Let's run our test case aleksandr@aleksandr-desktop:~ pw_test$ npx playwright test Running test using worker ✓ tests/first.test.js: : › top story navigation ( s) Slow test: tests/first.test.js ( s) passed ( s) /work/ 1 1 3 1 17 17 1 17 I highly recommend you to open the and play with CLI flags. official docs Dockerization Then we need to wrap our previous efforts into containers. ./Dockerfile FROM mcr.microsoft.com/playwright:v1 -focal WORKDIR /sanity-checks COPY /package.json . COPY /package-lock.json . COPY . ./ RUN npm install CMD [ , , ] .14 .1 "npx" "playwright" "test" ./.dockerignore node_modules infra I want to accentuate that Playwright has a bunch of its own images. Waiting for us to use them. Run our container in AWS Fargate configured with Terraform Now we need to run the container in AWS. The easiest way to do so is . It's a serverless solution with all the benefits of Paradigm. Fargate Also I suggest to use nifty . This tool provide us with the opportunity to define our infrastructure as a code. Terraform So this way we don't need to look at millions of services to understand which resources we use. Let's install terraform at your OS. Mac: brew tap hashicorp/tap brew install hashicorp/tap/terraform brew install awscli brew update Linux: sudo apt-get update && sudo apt-get install -y gnupg software-properties-common curl awscli curl -fsSL https: sudo apt-add-repository sudo apt-get update && sudo apt-get install terraform //apt.releases.hashicorp.com/gpg | sudo apt-key add - "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main" Windows: choco install awscli choco install terraform Verification of installation: aws --version terraform -help Then you need to run and provide AWS credentials. aws configure Then you need to manually create S3 bucket. In my case it's terraform-state-playwright In this bucket, Terraform will store information about our AWS infrastructure. This way we can work with it from different machines simultaneously. We don't need to worry about data-loss too. Afterwards, run: terraform init Then change infra/init.tf terraform { required_providers { aws = { source = version = } } backend { region = encrypt = bucket = key = } } provider { region = } "hashicorp/aws" "~> 3.0" "s3" "us-west-2" true "YOUR BUCKET NAME" "playwright.tfstate" "aws" "us-west-2" Now let's begin to create the actual AWS configs. First. You need to add networking. Let it be your default VPC and default subnets where our Fargate container will run. infra/vpc.tf resource {} resource { availability_zone = } resource { availability_zone = } "aws_default_vpc" "default" "aws_default_subnet" "default_az1" "us-west-2a" "aws_default_subnet" "default_az2" "us-west-2b" Next, we need to create the ECS configuration itself. infra/ecs.tf resource { name = } resource { name = tags = { Project = } } resource { name = } resource { family = execution_role_arn = aws_iam_role.ecs_task_execution_role.arn container_definitions = jsonencode([ { : { : , : { awslogs-group: aws_cloudwatch_log_group.playwright_tests.name, awslogs-region: , awslogs-stream-prefix: } }, : , : , } ]) network_mode = requires_compatibilities = [ ] cpu = memory = tags = { Project = } } "aws_ecr_repository" "playwright_tests" "playwright_tests" "aws_ecs_cluster" "playwright_tests" "playwright_tests" "playwright_tests" "aws_cloudwatch_log_group" "playwright_tests" "/ecs/playwright_tests" "aws_ecs_task_definition" "playwright_tests" "playwright_tests" logConfiguration logDriver "awslogs" options "us-west-2" "ecs" image "${aws_ecr_repository.playwright_tests.repository_url}:latest" name "playwright_tests" "awsvpc" "FARGATE" "2048" "4096" "playwright_tests" And IAM roles for our config infra/ecs_iam.tf data { statement { sid = effect = actions = [ ] principals { type = identifiers = [ ] } } } data { arn = } resource { name = assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json } resource { role = aws_iam_role.ecs_task_execution_role.name policy_arn = data.aws_iam_policy.ecs_task_execution_role_policy.arn } "aws_iam_policy_document" "assume_role_policy" "STSassumeRole" "Allow" "sts:AssumeRole" "AWS" "*" "aws_iam_policy" "ecs_task_execution_role_policy" "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" "aws_iam_role" "ecs_task_execution_role" "ecs-task-execution-role" "aws_iam_role_policy_attachment" "ecs_execution_role_attachment" Next we will create event_bridge which will trigger our Fargate Container every 5 minutes. infra/event_bridge.tf resource { name = schedule_expression = tags = { Project = } } resource { rule = aws_cloudwatch_event_rule.trigger_playwright_tests_cron_event.name arn = aws_ecs_cluster.playwright_tests.arn role_arn = aws_iam_role.role_for_event_bridge.arn ecs_target { task_count = task_definition_arn = aws_ecs_task_definition.playwright_tests.arn launch_type = network_configuration { subnets = [ aws_default_subnet.default_az1.id, aws_default_subnet.default_az2.id ] assign_public_ip = } } } "aws_cloudwatch_event_rule" "trigger_playwright_tests_cron_event" "trigger_playwright_tests_cron_event" "rate(5 minutes)" "playwright_tests" "aws_cloudwatch_event_target" "state_machine_target" 1 "FARGATE" true and according to IAM role infra/event_bridge_iam.tf resource { name = policy = jsonencode({ Version = , Statement = [ { : , : [ , , ], : }, { : , : [ , , ], : }, { : , : [ , ], : }, ] }) } resource { role = aws_iam_role.role_for_event_bridge.name policy_arn = aws_iam_policy.policy_for_event_bridge.arn } resource { name = assume_role_policy = data.aws_iam_policy_document.assume_role_policy.json tags = { Project = } } "aws_iam_policy" "policy_for_event_bridge" "policy_for_event_bridge" "2012-10-17" Effect "Allow" Action "ecs:RunTask" "ecs:StopTask" "ecs:DescribeTasks" Resource "*" Effect "Allow" Action "events:PutTargets" "events:PutRule" "events:DescribeRule" Resource "*" Effect "Allow" Action "iam:PassRole" Resource "*" "aws_iam_role_policy_attachment" "event_bridge_attach" "aws_iam_role" "role_for_event_bridge" "role_for_event_bridge" "playwright_tests" Deployment Now we are ready to apply everything. Just run: terraform plan to see the resources which will be created and then: terraform apply type yes The last step is to build and push your docker container. Go to: chose your repo and click https://us-west-2.console.aws.amazon.com/ecr/repositories?region=us-west-2 View push commands It's really simple step. Now we have our image pushed to ECR. You can automate this process with smth like CircleCI. There we go! Now we have our sanity checks up and running. If you want to destroy whole resources that you've created just run: terraform destroy Further steps... I don't want to bloat this article. So I suggest you implement notification in case of test failure by yourself. In my company, I used StepFunctions for this purpose. Also I highly recommend you official to start writing your own tests. Playwright documentation Github repo for this article: https://github.com/Xezed/playwright_tests Thank you for reading. Cheers! :)