<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: RakeshVardhan1</title>
    <description>The latest articles on DEV Community by RakeshVardhan1 (@rakeshvardhan1).</description>
    <link>https://dev.to/rakeshvardhan1</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F977777%2F6d58c3ba-fde6-4689-9dac-6e37b978cb4c.png</url>
      <title>DEV Community: RakeshVardhan1</title>
      <link>https://dev.to/rakeshvardhan1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rakeshvardhan1"/>
    <language>en</language>
    <item>
      <title>How To Build CI/CD Pipeline With TeamCity For Selenium Test Automation</title>
      <dc:creator>RakeshVardhan1</dc:creator>
      <pubDate>Thu, 24 Nov 2022 08:05:36 +0000</pubDate>
      <link>https://dev.to/testmuai/how-to-build-cicd-pipeline-with-teamcity-for-selenium-test-automation-39m3</link>
      <guid>https://dev.to/testmuai/how-to-build-cicd-pipeline-with-teamcity-for-selenium-test-automation-39m3</guid>
      <description>&lt;p&gt;&lt;a href="https://www.lambdatest.com/blog/what-is-continuous-integration-and-continuous-delivery/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Continuous Integration/Continuous Deployment&lt;/a&gt; (CI/CD) has become an essential part of modern software development cycles. As a part of continuous integration, the developer should ensure that the Integration should not break the existing code because this could lead to a negative impact on the overall quality of the project. In order to show how the integration process works, we’ll take an example of a well-known continuous integration tool, TeamCity. In this article, we will learn TeamCity concepts and integrate our test suites with TeamCity for &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;test automation&lt;/a&gt; by leveraging LambdaTest &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;cloud-based Selenium grid&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are numerous &lt;a href="https://www.lambdatest.com/learning-hub/cicd?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;best CI/CD tools&lt;/a&gt; available for building high-quality code and narrowing the gap between development and impacted teams. Besides establishing a DevOps culture in the organizations, teams enhance it by implementing &lt;a href="https://www.lambdatest.com/blog/16-best-practices-of-ci-cd-pipeline-to-speed-test-automation/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;best CI/CD practices&lt;/a&gt; throughout the Software Development Life Cycle(SDLC). These practices help the teams accelerate product development, automate the processes, and improve overall productivity.&lt;/p&gt;

&lt;p&gt;If you’re new to Selenium and wondering what it is then we recommend checking out our guide — &lt;a href="https://www.lambdatest.com/selenium?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;What is Selenium?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Which are the most wanted &lt;a href="https://www.lambdatest.com/blog/automation-testing-tools/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;tools for automation testing&lt;/a&gt; that have climbed the top of the ladder so far? Let’s take a look.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Jetbrains TeamCity?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AIAUWbBQxcsf09Q8F.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AIAUWbBQxcsf09Q8F.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;JetBrains TeamCity is a user-friendly and general-purpose CI/CD solution for developers and build engineers. TeamCity helps the team carry out all kinds of workflows and development practices within the SDLC life cycle.&lt;/p&gt;

&lt;p&gt;TeamCity comes in two different flavours.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;TeamCity Professional&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A free version of the software even for commercial use. We can connect up to three build agents and create up to a hundred build configurations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is multi-platform, multi-language, and multi-cloud — helps build, test, and deploy apps, packages, and containers of all sorts.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;TeamCity Enterprise&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An enterprise version of the same software where we can create unlimited build configurations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Manage hundreds of build agents with a single server. Connect multiple servers into a cluster if required.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Priority customer support from Jetbrains.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Can You Do With TeamCity?
&lt;/h2&gt;

&lt;p&gt;Let’s look at the following services offered by Teamcity for test automation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Self-hosted Continuous Integration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simultaneously run parallel builds on different platforms and environment configurations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configure the TeamCity continuous delivery pipelines via UI or configuration-as-code option using Kotlin DSL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Customize the statistics for different aspects — build duration, success rate, quality of the code, and custom metrics.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the code coverage and duplicates finder for Java and .NET environments.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: To know all the features of TeamCity, please have a look at the features overview section of the Jetbrains official site.&lt;/p&gt;

&lt;h2&gt;
  
  
  TeamCity Architecture
&lt;/h2&gt;

&lt;p&gt;Getting started with TeamCity has never been easier. Unlike some other build servers, TeamCity has distributed grid architecture, i.e., the TeamCity build system comprises two primary components — the server and a farm of build agents.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The TeamCity Server provides the user interface for managing build configurations and managing results. The server doesn’t run any jobs or tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The TeamCity Build agent executes build configurations or build jobs and can be installed on-premise or in cloud providers like AWS/Azure/GCP.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AOOmtJxQg3WTWlAGD.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AOOmtJxQg3WTWlAGD.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;TeamCity server initiates a build process whenever a specific condition is met. These conditions might be that there are changes in the VCS that TeamCity has detected. Many other conditions can trigger a build. Once a specific condition is met, the TeamCity server tries to identify the available agents based on the appropriate environment and compatibility. If there are no agents available, the build is added to the build queue. The build will be in the queue waiting for assigning to an agent. Once the build has been assigned to an agent, the agent has to get the sources to run the build.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TeamCity provides two possible options on how the build agent can get sources needed for the build:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Server-side Checkout: TeamCity server exports the required sources and passes them to the build agent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agent-side Checkout: The build agent itself checks out the sources before the build.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Once the build agent has all the required sources and files, it starts executing the build steps one after the other sequentially. Each step is represented by a specific build runner in this process — for example, maven, gradle, or sonarqube server, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As the build steps are being executed, the build agent sends all the log messages, code coverage results, testing reports, etc., to the TeamCity server instantly. Because of this, we can monitor the build process in real-time on the server console.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once all the build steps are executed, and the build is completed, the build agent sends the generated artifacts to the server. These are the files produced by the build — for example, WAR or JAR files, test reports, log data, etc.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;TeamCity supports development across all types of platforms, including Windows and Linux, macOS. TeamCity can be easily extended and integrated with other tools that make up the SDLC toolchain.&lt;/p&gt;

&lt;p&gt;Some of the integrations and toolchain that TeamCity support is shown below:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;TOOL CHAIN&lt;/th&gt;
&lt;th&gt;INTEGRATION&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Build Runners&lt;/td&gt;
&lt;td&gt;Apache ANT, Maven, Gradle, Microsoft .NET, Helm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testing Frameworks&lt;/td&gt;
&lt;td&gt;Junit, Nunit, TestNG, Apache ANT, Maven, MSTest, VSTest, MSpec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Version Control Systems&lt;/td&gt;
&lt;td&gt;Github, Gitlab, Bitbucket, Azure DevOps, Git, Subversion, Mercurial, Perforce&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Integrated Development Environments&lt;/td&gt;
&lt;td&gt;IntelliJ IDEA, Visual Studio, Eclipse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code Quality&lt;/td&gt;
&lt;td&gt;Inspection, Duplicates, Finder, Emma, JaCoCo, FxCop, dotCover, NCover&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud&lt;/td&gt;
&lt;td&gt;AWS, Google Cloud, Microsoft Azure, VMWare vSphere, Docker, Kubernetes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Defect Tracking Systems&lt;/td&gt;
&lt;td&gt;You Track, Jira, Github, Bitbucket, Azure DevOps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Others&lt;/td&gt;
&lt;td&gt;Unity, Octopus Deploy, SonarQube, Slack, JFrog, Snyk&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Advantages Of TeamCity
&lt;/h2&gt;

&lt;p&gt;TeamCity has the below advantages over other CI/CD solutions.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;For Developers&lt;/th&gt;
&lt;th&gt;For DevOps Engineers&lt;/th&gt;
&lt;th&gt;For Managers&lt;/th&gt;
&lt;th&gt;For Admins&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Perform Better&lt;/td&gt;
&lt;td&gt;Configuration as code&lt;/td&gt;
&lt;td&gt;Get a bird’s view of the CI&lt;/td&gt;
&lt;td&gt;Zero maintenance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Get started easily&lt;/td&gt;
&lt;td&gt;Pipeline Optimization&lt;/td&gt;
&lt;td&gt;Organize team’s work&lt;/td&gt;
&lt;td&gt;Scalability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test Intelligence&lt;/td&gt;
&lt;td&gt;Templates&lt;/td&gt;
&lt;td&gt;Can grow to any scale&lt;/td&gt;
&lt;td&gt;Cloud integrations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real-time reporting&lt;/td&gt;
&lt;td&gt;RESTFul API&lt;/td&gt;
&lt;td&gt;Benefit from a fast feedback loop&lt;/td&gt;
&lt;td&gt;Access Management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remote run and pre-tested commit&lt;/td&gt;
&lt;td&gt;Multiplatform and Multilanguage&lt;/td&gt;
&lt;td&gt;Professional technical support&lt;/td&gt;
&lt;td&gt;Rich plugin ecosystem&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  TeamCity Terminologies
&lt;/h2&gt;

&lt;p&gt;To perform test automation with TeamCity, let’s look at the concepts/terminology used within TeamCity.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Terminology&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TeamCity Server&lt;/td&gt;
&lt;td&gt;The major component in the TeamCity ecosystem that stores all the objects’ settings, manages the build queue, monitors the state of running builds, and performs many other tasks. We can have this server on-premise or in any cloud(AWS/GCP/Azure etc.) or TeamCity Cloud.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build Agent&lt;/td&gt;
&lt;td&gt;Build agent is the software that executes a build process as per the instructions from the server. Typically, it is installed and configured on a separate machine than the TeamCity server. TeamCity build agents can have multiple operating systems, different platforms, and also pre-configured environments.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Project&lt;/td&gt;
&lt;td&gt;TeamCity project is a collection of all different build configurations. We can create a project in TeamCity corresponding to a software project, specific release/version of a project, or any other logical grouping as per the product. These projects can be nested and organized into a tree-like structure.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build Configuration&lt;/td&gt;
&lt;td&gt;A build configuration in TeamCity is a collection of settings used to start a build or group the sequence of builds in the UI console.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VCS Root&lt;/td&gt;
&lt;td&gt;Whenever TeamCity needs to get the source code, it needs to connect to the version control system(VCS), referred to as a VCS root. TeamCity monitors the changes in VCS and gets the sources for a specific build configuration.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build Step&lt;/td&gt;
&lt;td&gt;Step is the task that needs to be executed, such as compiling the project, running code coverage, invoking the test tools, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build Trigger&lt;/td&gt;
&lt;td&gt;Triggers are used to add builds to the queue. We can add a trigger either when an event occurs (for ex. VCS check-in) or periodically with some configurable interval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Change&lt;/td&gt;
&lt;td&gt;Any modification to the source code of the project repository.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build&lt;/td&gt;
&lt;td&gt;It is the actual process of creating an application version. After the build process is triggered, it is added to the build queue and is started when there are agents available to run it. After the build is completed, the build agent sends build artifacts to the server.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build Queue&lt;/td&gt;
&lt;td&gt;Represents the list of builds that were triggered and are waiting to be started by the agents. TeamCity distributes the builds to the available agents as soon as they become idle.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build Artifacts&lt;/td&gt;
&lt;td&gt;After a build is completed, typically, we get files such as WAR/JAR files, installers, log files, etc. Once they are available for download, they are called build artifacts.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Want to know which are the 30 Top &lt;a href="https://www.lambdatest.com/blog/automation-testing-tools/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Automation Testing Tools&lt;/a&gt; in 2022? Let’s take a look.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mapping Some Concepts Of TeamCity With Jenkins
&lt;/h2&gt;

&lt;p&gt;As we all know, Jenkins is one of the most used CI/CD servers across different teams. Jenkins and TeamCity mainly provide the same set of concepts and functionalities but with slightly different naming conventions.&lt;/p&gt;

&lt;p&gt;The following table provides a mapping for some of the Jenkins concepts and terminology to the TeamCity counterparts.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Terminology&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Jenkins Master/Node&lt;/td&gt;
&lt;td&gt;TeamCity Server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dumb Slave/Permanent Agent&lt;/td&gt;
&lt;td&gt;Agent Pool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Executor&lt;/td&gt;
&lt;td&gt;TeamCity Agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;View or Folder&lt;/td&gt;
&lt;td&gt;Project&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Job/Item/Project&lt;/td&gt;
&lt;td&gt;Build Configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build&lt;/td&gt;
&lt;td&gt;Build Steps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pre Step&lt;/td&gt;
&lt;td&gt;Build Steps (Partially)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Post-Build Action&lt;/td&gt;
&lt;td&gt;Build Steps (Partially)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build Triggers&lt;/td&gt;
&lt;td&gt;Build Triggers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Source Control Management (SCM)&lt;/td&gt;
&lt;td&gt;Version Control System (VCS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workspace&lt;/td&gt;
&lt;td&gt;Build Checkout Directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pipeline&lt;/td&gt;
&lt;td&gt;Build Chain (via snapshot dependencies)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Label&lt;/td&gt;
&lt;td&gt;Agent Requirements&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  TeamCity Installation
&lt;/h2&gt;

&lt;p&gt;It’s a lot of theory! Now let’s install TeamCity, do some hands-on, and understand each of the concepts in detail.&lt;/p&gt;

&lt;p&gt;The TeamCity installation package is identical for both Professional and Enterprise editions. TeamCity can be installed and used in the following ways.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Direct installation package. (.exe for Windows, .tar.gz for Linux/macOS)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker Image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TeamCity Cloud — as a managed service&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s start with each of the options in detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Direct Installation Package
&lt;/h2&gt;

&lt;p&gt;On Windows — Navigate to TeamCity official download page and download the installation package. After downloading, you can start using TeamCity under the free Professional license right away. It is enabled by default.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Once the file is downloaded, run the file to start the installation process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Read and accept the Licence Agreement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose the folder in which you want to install the TeamCity or accept the default path provided. Click on Next.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As discussed above, TeamCity has two components — Server and Agent. Select the components as required to be used on the machine and click on Next.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since we will use the same machine as the Server and Agent, we will select both options. This approach is only applicable for learning and exploring TeamCity. Click on Next.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Let us choose port 8088 and proceed with the installation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On the next screen, TeamCity displays the build agent properties with the selected options. As chosen earlier, the server should be running on port 8088 and should be available on URL — &lt;a href="http://localhost:8088," rel="noopener noreferrer"&gt;http://localhost:8088,&lt;/a&gt; and the agent listens on port 9090 for all the server communication. Let’s not change any of these details, as we go with default values and click on Save.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once clicked on OK, we need to choose a user account to run the server and agent services. We select the SYSTEM account and click on Next.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the services to start on the machine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click Finish on the installation wizard. TeamCity web interface will be launched in a browser at the URL — &lt;a href="http://localhost:8088/" rel="noopener noreferrer"&gt;http://localhost:8088/&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;TeamCity might take some time to load all the components and show the UI. Choose the default data directory or use a custom folder to store all the build configuration and artifacts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AlJDnhWWnAZdxabhK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AlJDnhWWnAZdxabhK.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TeamCity stores all the build history and user-related data in a relational database. In the Database Connection setup screen, we can choose the appropriate SQL database. For the demo/training purposes, we could choose the internal database (HSQL) by TeamCity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: It is recommended to configure a database for production purposes before this and configure it with TeamCity as needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A6v4g12fkU2I7BCTW.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A6v4g12fkU2I7BCTW.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On Proceed, TeamCity will create a SQL database and provision all the required resources.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A5-Jg6yVsbjMV-6Sk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A5-Jg6yVsbjMV-6Sk.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once everything is ready, the License Agreement screen is displayed. Carefully read and accept the agreements, proceed to Next.&lt;/p&gt;

&lt;p&gt;TeamCity advised us to create an administrator account. Choose the details appropriately and click on Create Account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A_QzcDOzjrAW0jjUN.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A_QzcDOzjrAW0jjUN.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s it! The TeamCity installation and initial configuration are complete. We will be redirected to the TeamCity server home page as below.&lt;/p&gt;

&lt;p&gt;We could also choose to use the new experimental UI or continue using the classic UI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AyC5CelQkMOaaCCOZ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AyC5CelQkMOaaCCOZ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have chosen to use the new UI; hence the below home page will be displayed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2ATHyDZ8grVTQQYLNg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2ATHyDZ8grVTQQYLNg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The installation process is pretty similar in Linux and macOS. Please refer to these instructions for the same.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Perform browser automation testing on the most powerful cloud infrastructure. Leverage LambdaTest &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Automation Testing platform&lt;/a&gt; for faster, reliable and scalable experience on cloud.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Installation using Docker
&lt;/h2&gt;

&lt;p&gt;TeamCity can also be installed using docker. Login to the machine where Docker is present and follow the below instructions to install TeamCity. If you are not familiar with docker, please refer to these guidelines to install and set up.&lt;/p&gt;

&lt;p&gt;Typically, TeamCity is used with relational databases configured separately in production configurations. We will use Postgresql in these installation steps. This is how we are going to configure TeamCity here.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Linux machine1 — used as a server + postgres DB&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Linux machine2 — used as an agent&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;1. Using Linux Machine 1 As A Server + Postgres DB&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Login to machine1 and perform the below steps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Pull the postgres image as the root user on the linux machine.&lt;/p&gt;

&lt;p&gt;$ sudo su -&lt;br&gt;
$ docker pull postgres&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a directory named postgres in the docker volumes.&lt;/p&gt;

&lt;p&gt;$ mkdir -p $HOME/docker/volumes/postgres&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the postgres container with the below options.&lt;/p&gt;

&lt;p&gt;$ docker run --name pg-docker -e POSTGRES_PASSWORD=start123 -d -p 5432:5432 -v $HOME/docker/volumes/postgres:/var/lib/postgresql/data postgres&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are starting a new container from the postgres image with a name ‘pg-docker’ with default user ‘postgres’ and our own password ‘start123’. The port 5432 on the host machine is mapped to the port 5432 on the container. The folder/volume ‘$HOME/docker/volumes/postgres’ that we created in the previous step on the host machine is mapped to the ‘/var/lib/postgresql/data’ folder on the container. And using the flag -d we are starting the container in a detached mode.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Verify if the postgres container has started successfully using the below command.&lt;/p&gt;

&lt;p&gt;$ docker ps -a&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Make a note of the container-id for the postgres from the above command.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connect to the running container using the below command and create new ROLE, DATABASE and grant all the required permissions for the new user.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Replace the container id with the above-noted value.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker exec -it &amp;lt;container-id&amp;gt; bash
root@1c3102ea09d0:/# psql -U postgres
psql (13.2 (Debian 13.2-1.pgdg100+1))
Type "help" for help.

postgres=# CREATE ROLE teamcityuser with password 'start123' login;
CREATE ROLE
postgres=# create database teamcitydb with owner teamcityuser;
CREATE DATABASE
postgres=# grant all on database teamcitydb to teamcityuser;
GRANT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With all these steps, we are done with the setup required for the Postgres database.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Run the below commands to create the required folders for storing the TeamCity server-specific data and logs.&lt;/p&gt;

&lt;p&gt;$ cd ~&lt;br&gt;
$ mkdir teamcity&lt;br&gt;
$ cd teamcity&lt;br&gt;
$ mkdir data&lt;br&gt;
$ mkdir logs&lt;br&gt;
$ cd ~&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the below command to pull and start the TeamCity server.&lt;/p&gt;

&lt;p&gt;$ docker run -d --name teamcity-server -v /home/ec2-user/teamcity/data:/data/teamcity_server/datadir -v /home/ec2-user/teamcity/logs:/opt/teamcity/logs -p 8111:8111 -u 0 jetbrains/teamcity-server&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are starting a new container from the jetbrains/teamcity-server image with a name ‘teamcity-server’ and mapping port 8111 on the host machine to port 8111 on the container. The folders/volumes ‘/home/ec2-user/teamcity/data’ &amp;amp; ‘/home/ec2-user/teamcity/logs’ that we created in the previous step on the host machine are mapped to the ‘/data/teamcity_server/datadir’ &amp;amp; ‘/opt/teamcity/logs’ folders on the container respectively. And using the flag -d we are starting the container in a detached mode with root user using -u 0.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Docker takes some time to pull, extract the contents and start the container. Verify if the teamcity-server container has started successfully using the below command.&lt;/p&gt;

&lt;p&gt;$ docker ps -a&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the server has started, navigate to :8111 on the browser. We get the same screens as discussed in the native installation method. Navigate through all the required steps and proceed with the configuration.&lt;/p&gt;

&lt;p&gt;The only difference here is that since we have configured a postgres database, we need to configure it to use it with the TeamCity server. On the database connection setup screen, choose database type as PostgreSQL(step-1). Click on Refresh JDBC drivers(step-2). Enter the database host and port details(step-3). Enter the database name(step-4), username(step-5) and password(step-6) and click on Proceed.&lt;/p&gt;

&lt;p&gt;As we have created previously:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Host — machine1 IP address&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Port — 5432&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Database name — teamcitydb&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Database username — teamcityuser&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Database password — start123&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AAiPQsd42SZmGsZTY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AAiPQsd42SZmGsZTY.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Using Linux Machine 2 To Add An Agent To TeamCity Server&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Run the below commands to create the required folders for storing the TeamCity agent-specific data.&lt;/p&gt;

&lt;p&gt;$ cd ~&lt;br&gt;
$ mkdir teamcity&lt;br&gt;
$ cd teamcity&lt;br&gt;
$ mkdir data&lt;br&gt;
$ cd ~&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run the below command to pull and start the TeamCity agent.&lt;/p&gt;

&lt;p&gt;$ docker run -d --name teamcity-agent1 -e SERVER_URL="&lt;a&gt;teamcityserverhostipaddress:8111&lt;/a&gt;" -e AGENT_NAME="agent1" -v /home/ec2-user/teamcity/data:/data/teamcity_agent/conf -v /var/run/docker.sock:/var/run/docker.sock jetbrains/teamcity-agent&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Make sure to replace the teamcityserverhostipaddress with the TeamCity server IP address.&lt;/p&gt;

&lt;p&gt;We are starting a new container from the jetbrains/teamcity-agent image with a name ‘teamcity-agent1’ and connecting it to the TeamCity server which is running on another machine on port 8111. The folder/volume ‘/home/ec2-user/teamcity/data’ that we created in the previous step on the host machine is mapped to the ‘/data/teamcity_agent/conf’ folder on the container. And using the flag -d we are starting the container in a detached mode with agent name ‘agent1’.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Docker takes some time to pull, extract the contents and start the container. Verify if the teamcity-agent container has started successfully using the below command.&lt;/p&gt;

&lt;p&gt;$ docker ps -a&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the TeamCity server and agent setup are complete, we need to authorize the agent to start using it. Navigate to the server URL on the browser at :8111, click on Agents(step-1), click on Unauthorized tab(step-2) and select the agent and authorize(step-3).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AKp8gNWwDQ3G9e_mJ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AKp8gNWwDQ3G9e_mJ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s it! We can now start building the pipelines with TeamCity and use them for various jobs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Accelerate your release velocity with blazing fast &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;test automation cloud&lt;/a&gt;!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. TeamCity Cloud
&lt;/h2&gt;

&lt;p&gt;If you have observed the above two methods of installing TeamCity, we need to configure the server, agents and maintain the infrastructure on our own. Considering this, TeamCity has recently launched TeamCity Cloud, a fully-managed CI/CD solution that automatically runs the builds and tests in the cloud servers. It lets development teams deliver quality software faster and also at scale. This is currently available in the beta phase, and TeamCity is planning for a public release soon.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can navigate TeamCity Cloud and create your TeamCity instance on the cloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A3-tapDYuoc1NREVO.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A3-tapDYuoc1NREVO.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the request is approved, TeamCity will send a confirmation to the registered email address. As we see below, TeamCity configures the server and adds a couple of agent machines to the cloud instance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A7QFyAFSfVL0qMXKh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A7QFyAFSfVL0qMXKh.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As of now, TeamCity cloud is free based on certain build credits. Once it is officially released to the public, you need to take a subscription for using it. Using TeamCity cloud is one of the easiest ways to explore and learn it without any extra infrastructure setup or provisioning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Our First Build Configuration
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Whatever the TeamCity installation type you have followed, the below steps will be the same and applied for all instances.&lt;/p&gt;

&lt;p&gt;TeamCity configurations always start with a project. A project is a collection of all different build configurations. We can create a project in TeamCity corresponding to a software project, specific release/version of a project, or any other logical grouping as per the product. These projects can be nested and organized into a tree-like structure. This will enable the hierarchical display and propagate the settings across projects.&lt;/p&gt;

&lt;p&gt;TeamCity creates a Root project at the top of the project hierarchy. This project has most of the similar properties of a usual project. The settings and configurations made in the root project are available to all the other child projects created on the server.&lt;/p&gt;

&lt;p&gt;The root project is unique and has the below characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It is created by default, and we can’t remove it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is created as a top-level project; hence it has no parent project associated with it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It doesn’t have any build configurations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It does not appear in the normal user-level UI screens as it is primarily present as an entity in Administration UI only.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s start creating a new project by clicking on the Create Project button on the home screen and choose the option Manually. We will give the project details as below and create a simple HelloWorld project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A1v9M602rmIGXcjBp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A1v9M602rmIGXcjBp.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the project is created, we need to create a build configuration under it.&lt;/p&gt;

&lt;p&gt;A build configuration in TeamCity is a collection of settings used to start a build or group the sequence of builds in the UI console. Some examples of the build configurations are checking out the code, running the integration tests, building the artifact, etc. Build configuration is specific to a project, and it contains different builds. We can explore all the details of a build configuration on its home page or update it on the edit page.&lt;/p&gt;

&lt;p&gt;Click on Create Build Configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AsSWo1sl7uMoFc18F.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AsSWo1sl7uMoFc18F.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the below details and create the build configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AnlsGqJgbvd6NWmxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AnlsGqJgbvd6NWmxg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When creating a build configuration in TeamCity, we should configure the sequence of steps to be executed. These build steps are configured in the Build Steps section of the Build Configuration Settings page.&lt;/p&gt;

&lt;p&gt;We can perform these steps here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Adding new steps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using the auto-detect option in TeamCity to scan the VCS repo and choose the steps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy and delete the steps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Temporarily enable/disable the build steps.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AHEJyzmC1qhV3k2WJ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AHEJyzmC1qhV3k2WJ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on Add build step, choose the runner type as Command-Line, enter the script below, and finally save.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2Ailb7eod2eDv1NY0u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2Ailb7eod2eDv1NY0u.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are done with configuring our first build configuration in TeamCity for the HelloWorld project. We are good to run our build and see if it’s working. As you have noticed, we are trying to use the echo command to print the sample text to the console.&lt;/p&gt;

&lt;p&gt;On the build configuration page — we can see a Run button. Click on the Run button to start the build. TeamCity server starts the build and executes the build steps sequentially on the available agent. Once the build is completed, we can see and verify all the details using different tabs available.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A6zGXWAx26y9XN4KY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A6zGXWAx26y9XN4KY.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on Show full log to see the complete build log.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2APygdkwJOFwjC6zDb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2APygdkwJOFwjC6zDb.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TeamCity displays the complete build log. As we see in the image, the echoed text is printed to the console.&lt;/p&gt;

&lt;p&gt;That’s all! We can use TeamCity for test automation and create CI/CD pipelines for different purposes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Through this usability testing tutorial, you will learn how &lt;a href="https://www.lambdatest.com/learning-hub/usability-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;usability testing&lt;/a&gt; is a great way to discover unexpected bugs, find what is unnecessary or unused before going any further, and have unbiased opinions from an outsider.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using TeamCity for Running Selenium Test Automation
&lt;/h2&gt;

&lt;p&gt;Now we have got an understanding of installing and configuring TeamCity. Also, we created a project and were able to create build configurations, build steps, and run them. Let us explore creating CI/CD pipelines for running &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;test automation&lt;/a&gt; with TeamCity. &lt;a href="https://www.lambdatest.com/blog/selenium-webdriver-tutorial-for-cross-browser-testing/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium Webdriver&lt;/a&gt; is a collection of open-source libraries used for testing web applications. The API is used to automate the web application flow and verify if it’s working as expected or not. It supports most common browsers such as Firefox, Chrome, Safari, Edge, and Internet Explorer.&lt;/p&gt;

&lt;p&gt;Let us consider the below test case for our example. We use the Selenium Webdriver library to automate one of the UI flows on LambdaTest’s sample website — &lt;a href="https://lambdatest.github.io/sample-todo-app/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;https://lambdatest.github.io/sample-todo-app/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We will use WebDriver manager to configure the Firefox driver instance and use it further to interact with the elements of the page. We will also leverage TestNG to control the test execution flow — set up the driver before the test, running the actual test step, and close once the test execution has been completed.&lt;/p&gt;

&lt;p&gt;Complete code for the below example is available on &lt;a href="https://github.com/rakesh-vardan/teamcity-selenium-lambdatest" rel="noopener noreferrer"&gt;Github&lt;/a&gt; here for reference.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.lambdatest;

import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

public class Lambdatest {

   public WebDriver driver;

   @BeforeTest
   public void setUp() {
       WebDriverManager.firefoxdriver().setup();
       driver = new FirefoxDriver();
   }

   @Test
   public void testScript() {
       try {
           driver.get("https://lambdatest.github.io/sample-todo-app/");
           driver.findElement(By.name("li1")).click();
           driver.findElement(By.name("li2")).click();
           driver.findElement(By.id("sampletodotext")).clear();
           driver.findElement(By.id("sampletodotext")).sendKeys("Yey, Let's add it to list");
           driver.findElement(By.id("addbutton")).click();
           driver.quit();
       } catch (Exception e) {
           System.out.println(e.getMessage());
       }
   }

   @AfterTest
   public void teardown() {
       if (driver != null) {
           driver.quit();
       }
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The complete project structure is as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A6M0M5Ov98FCz19yM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A6M0M5Ov98FCz19yM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let us begin with creating a new TeamCity project for running the automated tests in Selenium. Click on Create Project and choose From a repository URL. Since TeamCity needs to pull the code from any repository like GitHub, BitBucket, or Gitlab — we need to configure it using this option.&lt;/p&gt;

&lt;p&gt;Enter the below details — repository URL for Github, username, password (if required) and click on Proceed. Username and password are not mandatory and needed only for the repositories, which require authentication for cloning operation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AkcNqvIKc6oO1NR_1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AkcNqvIKc6oO1NR_1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TeamCity makes a connection to the provided repository and displays the below screen. Proceed with the defaults or choose the required branch name and build a name as needed. In our case, we are proceeding with the master branch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A82xjeIIfzFqj4fIW.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A82xjeIIfzFqj4fIW.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Upon clicking on Proceed, TeamCity creates a project, build configuration, and VCS root as appropriate as below. TeamCity is also intelligent enough to scan the whole repository and suggest the required build steps automatically.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AQfzfLkjfraI0i1U2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AQfzfLkjfraI0i1U2.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since we are using a Java-based project with maven as the build tool, TeamCity has detected that we would like to run the maven commands, specifically the maven goal clean test and pom.xml.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AbxxorEua0G3DUymj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AbxxorEua0G3DUymj.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can either choose the suggested build step by TeamCity or proceed with creating a new one. We would select the recommended step here and click on Use Selected. A new build step would be added to the build configuration as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AUc_JwqrrdGhywQKu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AUc_JwqrrdGhywQKu.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on Edit and verify the configurations that TeamCity adds by default.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AoDc1OViRg6q4IMUS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AoDc1OViRg6q4IMUS.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also see the advanced options and configure them as needed. Since in our example, we need to let maven know which suite file to run the tests from, we should pass additional command line parameters. Update the command line parameter as below. The important note here is that we added a build step in the TeamCity build configuration to execute the maven goal clean test using the maven runner. Once everything looks good, click on Save.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AwmYyCTUbqZIRsAqO.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AwmYyCTUbqZIRsAqO.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now our build configuration is completed with the required steps to run the build. Before running, let us have a look at the Version Control Settings option. Click on Version Control Settings in the left pane. The configuration looks as below at the moment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AUvytr2b4jKOXZi2P.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AUvytr2b4jKOXZi2P.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we see above in the Version Control Settings pane, a new VCS Root has been added to the build configuration. Whenever TeamCity needs to get the source code, it needs to make a connection to the version control system(VCS), which is referred to as a VCS root. TeamCity monitors the changes in VCS and gets the sources for a specific build configuration. All these configuration parameters, such as the path to the VCS repository source, user name, password, and any additional settings, are represented by the VCS root only.&lt;/p&gt;

&lt;p&gt;VCS roots are created within a project. Once created they are available to all the build configurations added to that project and its child projects. We can configure more than VCS root to a build configuration. We can even configure additional options using the Show Advanced Options; also, we can create custom checkout rules.&lt;/p&gt;

&lt;p&gt;Click on the Run button to trigger and execute the build steps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxtwm2kyijz326oh4hxs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuxtwm2kyijz326oh4hxs.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TeamCity starts pulling the latest code from the VCS root and specific branches and executing the build steps one by one. In our case, there is only one step to run the maven goal. So it starts pulling the required dependencies to build the project and starts the tests. Once all the build steps are executed, we see the below screen with the overall status.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AHon2LbK6gQl3gFdl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AHon2LbK6gQl3gFdl.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let us click on the Show Full log option to see the whole execution log for the run.&lt;/p&gt;

&lt;p&gt;As we see below, the expected maven command is executed, and the tests are completed.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mvn clean install -DsuiteXmlFile=testnglocal.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AZD7z1E0a_ka_XzBK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AZD7z1E0a_ka_XzBK.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is great! We can run a Selenium Automated test in our local machine using the build configuration that we have just created in TeamCity. We could also leverage some of the below additional features of TeamCity for test automation and develop robust TeamCity build pipelines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Triggers:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Triggers are used to add builds to the queue. We can add a trigger when an event occurs (for ex. VCS check-in) or periodically with some configurable interval. We could use a schedule trigger and configure to run the build periodically — this is used while configuring the test suite for nightly regression execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parameters:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Parameters in TeamCity enable the users to share different settings with the running build. These are key-value pairs, which can be defined by the user or provided by TeamCity.&lt;/p&gt;

&lt;p&gt;There are three types of build parameters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Environment variables are passed into the generated build process as environment and defined with the env. prefix.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;System properties are passed into the build scripts of the TeamCity’s supported runners as variables and are defined with the system. prefix. They are specific to a build tool.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Configuration parameters are not passed into the build but are only supposed to share the settings within a build configuration. These are useful for customizing a build configuration based on a template. They don’t contain any prefixes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Failure conditions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can define the conditions under which TeamCity marks a build as failed. These are some of the available conditions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AzAXs5yd-ehMPHxLg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AzAXs5yd-ehMPHxLg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build Features&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A building feature is an additional functionality that we can add to TeamCity’s build configuration. It affects the running builds and results. We could add a build feature to process the XML reports generated by TestNG after the test execution is over.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Statistics&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When we have multiple projects and several build configurations, tracking all those statistics is very important. TeamCity collects all the statistical data across builds and presents a visual chart for easy analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AvBpLuy-OGi0hizMs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AvBpLuy-OGi0hizMs.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DSL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Besides storing the settings in a version-controlled system, TeamCity also allows storing the settings as a Kotlin DSL(Domain Specific Language). Using the DSL configuration stored in version control systems enables you to define the settings programmatically. Since Kotlin is a statically typed language, you automatically receive the auto-completion feature in an IDE, discovering available API options much more straightforward.&lt;/p&gt;

&lt;p&gt;Coming back to our example, we have executed our tests in only one browser — firefox. What if we need to run the tests in other browsers as well? And we might have some of the below requirements from the TeamCity test automation perspective.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Save the test execution reports and logs over some time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Able to spin up different browsers including multiple versions i.e. Cross-Browser Testing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integrate the test framework with other tools like Jira or GitHub, or Trello for bug creation on failure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support a vast number of tests — thousands of tests across different browsers, OS, and resolutions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To achieve all this, we need a solution that caters to all the requirements and helps us do continuous testing, providing early feedback to the development team. &lt;a href="https://www.lambdatest.com/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;LambdaTest&lt;/a&gt; is one such solution to all these requirements. In the next section, we will integrate our example with the LambdaTest &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;cloud Selenium grid&lt;/a&gt; and perform the test automation using TeamCity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integration With LambdaTest Cloud-Based Selenium Grid
&lt;/h2&gt;

&lt;p&gt;LambdaTest is a &lt;a href="https://www.lambdatest.com/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;cross-browser testing&lt;/a&gt; cloud solution to perform live interactive and automated cross-browser testing on 3000+ real browsers and operating systems online. It is one of the most often used Selenium grid solutions for many companies.&lt;/p&gt;

&lt;p&gt;To get started with the LambdaTest cloud, navigate to &lt;a href="https://accounts.lambdatest.com/register?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;LambdaTest Register Page&lt;/a&gt; and sign-up for a new account. Once your LambdaTest account is activated, go to your &lt;a href="https://accounts.lambdatest.com/login?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Profile&lt;/a&gt; section and note the username and access key. We would need these LambdaTest username and access key to execute our tests on the LambdaTest platform.&lt;/p&gt;

&lt;p&gt;Before using LambdaTest with our TeamCity build pipeline, we need to download and install the plugin from the marketplace.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Visit the JetBrains marketplace and download the “LambdaTest” plugin.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To install the downloaded TeamCity plugin, follow the below steps to upload the plugin on your TeamCity server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to your server Administration and then to Plugins List.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose the option Upload plugin zip in the Plugins screen.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose the zip file and upload it to TeamCity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once uploaded, click on Enable uploaded plugins.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At this moment, we can see the LambdaTest plugin added to the External Plugins as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqvcr43b8swn7i5i4amc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcqvcr43b8swn7i5i4amc.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now go to the existing Selenium test build configuration, and update the required testng XML file in the Additional Maven command line parameters.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2Ac1AB89HluK92DedK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2Ac1AB89HluK92DedK.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on Build Features and then click on Add build feature. Select LambdaTest from the dropdown list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AMIbzVuBEBPbW_RFL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AMIbzVuBEBPbW_RFL.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the username, and access token noted as above and save. The build feature for LambdaTest is added now, and these values/parameters are passed to our test case once the build is started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A8qgvZTYskguSDkD9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2A8qgvZTYskguSDkD9.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run the build. Once the build has started, navigate to the &lt;a href="https://accounts.lambdatest.com/login?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;LambdaTest Automation dashboard&lt;/a&gt; and verify the execution status.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2ACHK0N-qeBSnSqqn_.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2ACHK0N-qeBSnSqqn_.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LambdaTest also provides all the test logs and recordings of the test execution as below. It will be very helpful for any issues with the script and using logs we can debug and identify the root cause of the issue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AFi1Zlpm3ahbZlj1W.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AFi1Zlpm3ahbZlj1W.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above example, we have executed our tests on the Chrome browser on Windows OS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AxykddUMncipY9rb1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AxykddUMncipY9rb1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LambdaTest also provides the &lt;a href="https://www.lambdatest.com/capabilities-generator/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;desired capabilities generator&lt;/a&gt; to help us with the required configuration values to run the tests on different platform combinations. It is a valuable utility and comes in handy while working with cross-browser testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;A comprehensive User Acceptance Testing (UAT) tutorial that covers what User &lt;a href="https://www.lambdatest.com/learning-hub/user-acceptance-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;acceptance testing&lt;/a&gt; is, its importance, benefits, and how to perform it with real-time examples.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We have now successfully learned how to create a CI/CD pipeline using TeamCity and performed Selenium test automation on the LambdaTest cloud grid. We have covered some of the essential concepts used in TeamCity that help build pipelines and use them for test automation.&lt;/p&gt;

&lt;p&gt;There are &lt;a href="https://www.lambdatest.com/blog/benefits-of-ci-cd/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov24_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;numerous CI/CD benefits&lt;/a&gt; and among them, TeamCity is a robust CI/CD solution to manage the pipelines, and in turn, helps the teams to follow best practices of Continuous Testing and other DevOps principles. We can even integrate IDE like IntelliJ with TeamCity plugins and start running the jobs from the IDE itself. Teams can build robust pipelines using TeamCity and leverage LambdaTest cloud grid solution for achieving excellent test automation benefits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Building and Testing!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Building A CI/CD Pipeline With Travis CI, Docker, And LambdaTest</title>
      <dc:creator>RakeshVardhan1</dc:creator>
      <pubDate>Wed, 23 Nov 2022 16:49:25 +0000</pubDate>
      <link>https://dev.to/testmuai/building-a-cicd-pipeline-with-travis-ci-docker-and-lambdatest-9al</link>
      <guid>https://dev.to/testmuai/building-a-cicd-pipeline-with-travis-ci-docker-and-lambdatest-9al</guid>
      <description>&lt;p&gt;With the help of well-designed Continuous Integration systems in place, teams can build quality software by developing and verifying it in smaller increments. &lt;a href="https://www.lambdatest.com/blog/what-is-continuous-integration-and-continuous-delivery/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Continuous Integration (CI)&lt;/a&gt; is the process of pushing small sets of code changes frequently to the common integration branch rather than merging all the changes at once. This avoids big-bang integration before a product release. &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Test automation&lt;/a&gt; and Continuous Integration are an integral part of the software development life cycle. As the benefits of following DevOps methodology in a development team becomes significant, teams have started using different tools and libraries like Travis CI with Docker to accomplish this activity.&lt;/p&gt;

&lt;p&gt;In this blog, we will discuss the role of Travis CI in Selenium test automation and dive deep into using Travis CI with Docker. We will also look at some effective Travis CI and Docker examples. We would also integrate and &lt;a href="https://www.lambdatest.com/automate-selenium-tests-with-travisci?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;automate Selenium tests suites with Travis CI&lt;/a&gt; on the LambdaTest cloud grid.&lt;/p&gt;

&lt;p&gt;Without further ado, Let’s build a CI/CD pipeline with Travis CI, Docker, and LambdaTest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Perform browser &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=medium&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;test automation&lt;/a&gt; testing on the most powerful cloud infrastructure. Leverage LambdaTest automation testing for faster, reliable and scalable experience on cloud.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview Of Travis CI
&lt;/h2&gt;

&lt;p&gt;Travis CI is a cloud-based service available for teams for building and testing applications. As a continuous integration platform, Travis CI supports the development process by automatically building and testing the code changes, providing immediate feedback if the change is successful. It can also help us automate other steps in the software development cycle, such as managing the deployments and notifications.&lt;/p&gt;

&lt;p&gt;Travis CI can build and test projects on the cloud platform hosted on code repositories like GitHub. We could also use other &lt;a href="https://www.lambdatest.com/blog/best-ci-cd-tools/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;best CI/CD tools&lt;/a&gt; such as Bitbucket, GitLab, and Assembla, but some of them are still in the beta phase. When we run a build, Travis CI clones the repository into a brand-new virtual environment and performs a series of steps to build and test the code.&lt;/p&gt;

&lt;p&gt;When a build is triggered, Travis CI clones the GitHub repository into a brand-new virtual environment and performs a series of tasks to build and test the code. If any of those jobs fails, the build is considered broken; else, the build is successful. On the success of the build, Travis CI will deploy the code to a web server or an application host.&lt;/p&gt;

&lt;p&gt;In case you are eager to learn about the Travis CI/CD pipeline, please refer to our detailed blog that deep dives into how to build your first &lt;a href="https://www.lambdatest.com/blog/build-your-first-ci-cd-pipeline-with-travis-ci/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;CI/CD pipeline with Travis CI&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  .travis.yml Configuration
&lt;/h2&gt;

&lt;p&gt;Builds on Travis CI are configured mostly through the build configuration defined in the file .travis.yml in the code repository. It allows the configuration to be version-controlled and flexible. Once the application code is completed, we need to add the .travis.yml file to the repository.&lt;/p&gt;

&lt;p&gt;It contains the instructions on what to build and how exactly to test the application. Travis CI performs all the steps configured in this YAML file.&lt;/p&gt;

&lt;p&gt;Some of the commonly used terms associated with Travis CI are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Job&lt;/strong&gt; — Job is an automated process that clones the code repository into a brand-new virtual environment and performs a set of actions such as compiling the code, running tests, deploying the artifact, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Phase&lt;/strong&gt; — Job is a collection of different phases. Sequential steps, aka phases, collectively create a job in Travis CI. For example, install phase, script phase, before_install phase, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build&lt;/strong&gt; — Build refers to a group of jobs that are running in a sequence. For example, a build can have two jobs defined in it. Each job tests the project with a different version of the programming language. The build is finished only when all of its jobs have completed execution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stage&lt;/strong&gt; — Stage refers to the group of jobs that run in parallel.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Features Of Travis CI
&lt;/h2&gt;

&lt;p&gt;Some of the salient features that Travis CI provides as a CI/CD platform are given below:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Free cloud-based hosting&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automatic integration with GitHub&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Safelisting or Blocklisting branches&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pre-installed tools and libraries for build and test&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provision to add build configuration via a shell script&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Caching the dependencies&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Building Pull-Requests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support for multiple programming languages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build Configuration Validation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easily set up CRON jobs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In case you want to deep dive into how Jenkins (the preferred open-source CI/CD tool) stacks up against Travis CI, please refer to our blog &lt;a href="https://www.lambdatest.com/blog/travis-ci-vs-jenkins/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Travis CI Vs. Jenkins&lt;/a&gt; to make an informed decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Accelerate your release velocity with blazing fast &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=medium&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;automated testing&lt;/a&gt; on cloud!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview Of Docker
&lt;/h2&gt;

&lt;p&gt;According to the Stack overFlow 2021 Developer survey, Docker is one of the most used containerization platforms to develop, ship, and run applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AQIIVEK7aH7SjHQLW.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AQIIVEK7aH7SjHQLW.png" width="447" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docker enables us to separate applications from the infrastructure so that the application software can be delivered quickly. In short, Virtual Machines(VM) virtualizes the hardware, whereas Docker virtualizes the Operating System(OS).&lt;/p&gt;

&lt;p&gt;In a Virtual Machine — multiple operating systems are run on a single host machine using the virtualization technology known as Hypervisor. Since the full OS needs to be loaded, there may be a delay while booting up the machines; also, there is an overhead of installing and maintaining the operating systems. Whereas in Docker, the host operating system itself is leveraged for virtualization.&lt;/p&gt;

&lt;p&gt;Docker daemon, installed on the host machine, manages all the heavy lifting tasks like listening to the API requests, managing docker objects (images, containers, and volumes), etc. In case you are looking to leverage Docker with Selenium, do check out our detailed blog that outlines how to run &lt;a href="https://www.lambdatest.com/blog/run-selenium-tests-in-docker/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium tests in Docker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Some of the useful concepts Docker leverages from the Linux world are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Namespaces&lt;/strong&gt; — Docker uses a technology called namespaces to provide the isolated workspace called container. For each container, Docker creates a set of namespaces when we launch it. Some namespaces in Linux are pid, net, ipc, mnt, and uts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Control Groups&lt;/strong&gt; — Docker Engine on Linux also uses another technology known as control groups (cgroups). A cgroup restricts an application to a limited set of resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Union file systems&lt;/strong&gt; — Union file systems, or UnionFS, are lightweight and fast file systems that work by creating layers. Docker Engine makes use of UnionFS to provide container building blocks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Container Format&lt;/strong&gt; — Docker Engine combines the namespaces, control groups, and UnionFS into a container format wrapper. The default container format is libcontainer.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Basics Of Docker
&lt;/h2&gt;

&lt;p&gt;Docker uses a client-server architecture at its core. Some of the common objects and terminology used in Docker are explained below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Image&lt;/strong&gt; — An image is a read-only template with all the required instructions to create a Docker container. The image is a collection of files and metadata. These files collectively form the root filesystem for the container. Typically images are made up of layers which are stacked on top of each other. And these images can share layers to optimize disk usage, memory usage, and transfer times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Container&lt;/strong&gt; — Container is the runnable instance of an image. Containers have their lifecycle to create, start, stop, delete, and move using the Docker client API commands. Containers are by default isolated from other containers and the host machine. Basically, the container is defined by the image it is created from. If required, we need to give specific configuration or environment variables before starting it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Engine — Docker Engine is a client-server application that includes the following major components.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A server is a form of long-running application known as a daemon process (i.e. the Dockerd command).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A REST API defines interfaces that applications can use to communicate with the daemon and instruct it on what needs to be done.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A client for the command-line interface (CLI) (i.e. the Docker command).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Registry&lt;/strong&gt; — Registry is a place where all the Docker images are stored and distributed. Docker hub manages all the openly available docker images.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network&lt;/strong&gt; — Docker uses a networking subsystem on the configurable host OS, using different drivers. These drivers provide the core networking functionality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bridge&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Host&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Overlay&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Macvlan&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;none&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Volume&lt;/strong&gt; — Since Docker containers are ephemeral by default, we need a provision to store the data between 2 different containers. Docker volumes provide this functionality where the data is persisted across containers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt; — It is a flat-file with instructions on how to create an image and run it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Docker-compose&lt;/strong&gt; — Docker compose is a utility tool for defining and running multi-container docker applications. Here we use a YAML file to configure the services required for the application. By using a single command, we can start all the services and also establish dependencies between them.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;This article explains the &lt;a href="https://www.lambdatest.com/blog/emulator-vs-simulator-vs-real-device/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;emulator vs simulator&lt;/a&gt; vs real device differences, the learning of which can help you select the right mobile testing solution for your business.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Integrate Travis CI with Selenium using Docker
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Using Docker Images
&lt;/h2&gt;

&lt;p&gt;Now that we have understood the fundamentals of Travis CI and Docker let us start using them together to run some UI tests with Selenium WebDriver.&lt;/p&gt;

&lt;p&gt;The first step is to define a test scenario for our Travis CI and Docker Example. Here is the Selenium test scenario:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open a specific browser — Chrome, Firefox, or Edge&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Navigate to the &lt;a href="https://lambdatest.github.io/sample-todo-app/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;sample application&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Verify headers on the page&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the first two checkboxes and see if they are selected&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clear the textbox — Want to add more and enter some text into it and click on Add&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check if the new item is added to the list and verify its text&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the code that we need to write using Selenium WebDriver agnostic of any browser. First, we use the BrowserFactory to instantiate the browser based on the input and pass it on to our tests.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.lambdatest;

import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class SeleniumTests extends BaseTest {

    @BeforeTest
    public void setUp() {
        driver.get("https://lambdatest.github.io/sample-todo-app/");
    }

    @Test(priority = 1)
    public void verifyHeader1() {
        String headerText = driver.findElement(By.xpath("//h2")).getText();
        assertThat(headerText).isEqualTo("LambdaTest Sample App");
    }

    @Test(priority = 2)
    public void verifyHeader2() {
        String text = driver.findElement(By.xpath("//h2/following-sibling::div/span")).getText();
        assertThat(text).isEqualTo("5 of 5 remaining");
    }

    @Test(priority = 3)
    public void verifyFirstElementBehavior() {
        WebElement firstElementText = driver.findElement(By.xpath("//input[@name='li1']/following-sibling::span[@class='done-false']"));
        assertThat(firstElementText.isDisplayed()).isTrue();
        assertThat(firstElementText.getText()).isEqualTo("First Item");

        assertThat(driver.findElement(By.name("li1")).isSelected()).isFalse();
        driver.findElement(By.name("li1")).click();
        assertThat(driver.findElement(By.name("li1")).isSelected()).isTrue();

        WebElement firstItemPostClick = driver.findElement(By.xpath("//input[@name='li1']/following-sibling::span[@class='done-true']"));
        assertThat(firstItemPostClick.isDisplayed()).isTrue();

        String text = driver.findElement(By.xpath("//h2/following-sibling::div/span")).getText();
        assertThat(text).isEqualTo("4 of 5 remaining");
    }

    @Test(priority = 4)
    public void verifySecondElementBehavior() {
        WebElement secondElementText = driver.findElement(By.xpath("//input[@name='li2']/following-sibling::span[@class='done-false']"));
        assertThat(secondElementText.isDisplayed()).isTrue();
        assertThat(secondElementText.getText()).isEqualTo("Second Item");

        assertThat(driver.findElement(By.name("li2")).isSelected()).isFalse();
        driver.findElement(By.name("li2")).click();
        assertThat(driver.findElement(By.name("li2")).isSelected()).isTrue();

        WebElement secondItemPostClick = driver.findElement(By.xpath("//input[@name='li2']/following-sibling::span[@class='done-true']"));
        assertThat(secondItemPostClick.isDisplayed()).isTrue();

        String text = driver.findElement(By.xpath("//h2/following-sibling::div/span")).getText();
        assertThat(text).isEqualTo("3 of 5 remaining");
    }

    @Test(priority = 5)
    public void verifyAddButtonBehavior() {
        driver.findElement(By.id("sampletodotext")).clear();
        driver.findElement(By.id("sampletodotext")).sendKeys("Yey, Let's add it to list");
        driver.findElement(By.id("addbutton")).click();
        WebElement element = driver.findElement(By.xpath("//input[@name='li6']/following-sibling::span[@class='done-false']"));
        assertThat(element.isDisplayed()).isTrue();
        assertThat(element.getText()).isEqualTo("Yey, Let's add it to list");
    }

    @AfterTest
    public void teardown() {
        if (driver != null) {
            driver.quit();
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We are using TestNG and adding appropriate annotations for our tests. We also configured the testng.xml file to include what tests to run.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;

&amp;lt;!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"&amp;gt;
&amp;lt;suite name="All Test Suite"&amp;gt;
    &amp;lt;test verbose="2" name="travisci-selenium-docker-lambdatest"&amp;gt;
        &amp;lt;parameter name="browser" value="GRID_CHROME"&amp;gt;
            &amp;lt;parameter name="gridHubURL"
                       value="http://localhost:4444/wd/hub"/&amp;gt;
        &amp;lt;/parameter&amp;gt;
        &amp;lt;classes&amp;gt;
            &amp;lt;class name="com.lambdatest.SeleniumTests"&amp;gt;
                &amp;lt;methods&amp;gt;
                    &amp;lt;include name="verifyHeader1"/&amp;gt;
                    &amp;lt;include name="verifyHeader2"/&amp;gt;
                    &amp;lt;include name="verifyFirstElementBehavior"/&amp;gt;
                    &amp;lt;include name="verifySecondElementBehavior"/&amp;gt;
                    &amp;lt;include name="verifyAddButtonBehavior"/&amp;gt;
                &amp;lt;/methods&amp;gt;
            &amp;lt;/class&amp;gt;
        &amp;lt;/classes&amp;gt;
    &amp;lt;/test&amp;gt;
&amp;lt;/suite&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And finally, we use the below Maven command to trigger the tests. In case you are relatively new to Maven, do check out our detailed blog that will help you getting started with &lt;a href="https://www.lambdatest.com/blog/getting-started-with-maven-for-selenium-testing/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Maven for Selenium Automation&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=GRID_FIREFOX -DgridHubURL=http://localhost:4444/wd/hub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The entire code for this project is available on the GitHub repository.&lt;/p&gt;

&lt;p&gt;Since our goal is to configure and run the Selenium tests using Travis CI and Docker, you should check the following prerequisites:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Active GitHub account, with the code repository available in GitHub.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Active TravisCI account and the required permissions to access the repository from GitHub.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once all these prerequisites are met, let’s take a quick look at the travis.yml file configured in the project.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist: trusty
language: java

jdk:
  - oraclejdk8

before_script:
  - docker run -d -p 4444:4444 -v /dev/shm:/dev/shm selenium/standalone-firefox:4.0.0-rc-1-prerelease-20210618
  - docker ps

script:
  - mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=GRID_FIREFOX -DgridHubURL=http://localhost:4444/wd/hub

cache:
  directories:
    - .autoconf
    - $HOME/.m2

deploy:
  provider: releases
  api_key: ${api_key}
  skip_cleanup: true
  file: [ "target/surefire-reports/emailable-report.html",
          "target/surefire-reports/index.html" ]
  on:
    all_branches: true
    tags: false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As we learned earlier, travis.yml is the configuration file that we use to instruct the Travis CI cloud server on what actions to perform for the given project.&lt;/p&gt;

&lt;p&gt;Let’s understand all these details one by one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dist&lt;/strong&gt;: When a new job is started in Travis CI, it spins up a new virtual environment in the cloud infrastructure. Each build is run in the pre-configured virtualization environments. Then, using the dist key, we specify the infrastructure needed to be spun up by the server. Some of the available values for dist in the Linux environment are trusty, precise, bionic, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;language&lt;/strong&gt;: Language key is used to specify the language support needed during the build process. We can choose the language key appropriately from the list of available values. Some examples include Java, Ruby, Go, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;jdk&lt;/strong&gt;: The key JDK is used while the language key is selected as Java. We basically give the version of the JDK that needs to be used while building the project. In our case, it should be oraclejdk8 as we are using Java 1.8 version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;script&lt;/strong&gt;: Script key is used to run the actual build command or script specific to the selected language or environment. In the example, we use mvn commands as we have created a maven-based project for the example.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;before_script&lt;/strong&gt;: It is used to run any commands before running the actual script commands. Before running the Maven command in the script phase, we need to ensure the Docker environment is set up successfully.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;cache&lt;/strong&gt;: This key is used to cache the content that doesn’t change frequently, and running this can help speed up the build process. Cache has many supported keys available for different caching strategies. Some of them are directories, npm, cache, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;directories&lt;/strong&gt;: This is a caching strategy used for caching the directories based on the given string path.&lt;/p&gt;

&lt;p&gt;We can also use the build configure explorer from Travis CI and check how the Travis CI system reads and understands the configuration. This is helpful in validating the configuration, adding the correct keys, and updating as per the latest specifications.&lt;/p&gt;

&lt;p&gt;Once the prerequisites mentioned above are met, we can start with our build-in Travis CI with Docker. There are various ways in which we can start the builds.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Commit the code and push to Github; the default hook will trigger a new build on the server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Manually trigger a build from the dashboard views.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Trigger with the Travis CI API.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the default dashboard view of my user in Travis CI. As we can see, I have activated only two projects from GitHub.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AaG-z1QZdZo3JXJ3E.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AaG-z1QZdZo3JXJ3E.png" width="512" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From any of the options described above, Travis CI will start performing the below actions when a build is triggered:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Reads the configuration defined in travis.yml&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adds the build to the job queue&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start creating the brand new virtual environment to execute the steps mentioned in the travis.yml file&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AFjg3-qU6w0uFFSOg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AFjg3-qU6w0uFFSOg.png" width="512" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the View config tab, we can also see the build configuration as read by Travis CI. Since we haven’t specified any os value in the travis.yml file, it takes the default value as Linux and proceeds with the build set-up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A9pFHsInwWZ0fG4MF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A9pFHsInwWZ0fG4MF.png" width="512" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the build is completed, we could see the image banner which indicates that the build has passed successfully. It also gives us other information such as branch information, time taken for execution, latest commit message, operating system information, build environment, etc.&lt;/p&gt;

&lt;p&gt;Let’s navigate to the Job log section and understand what Travis CI and Docker have performed for our build.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AxBVgq6YvAoveKNTY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AxBVgq6YvAoveKNTY.png" width="512" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Job log section, we can see the complete log information for the current job. As seen below, Travis CI has spun up the below worker for our build. It has created a new instance in the Google Cloud Platform, and the start-up time is around 6.33 seconds.&lt;/p&gt;

&lt;p&gt;Travis CI will dynamically decide which platform (like GCP Compute Engine or AWS EC2 machines) to choose for the instance. If an enterprise version is used, we could also configure our infrastructure to be used by Travis CI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AK1dOUyV9tN_hCuMK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AK1dOUyV9tN_hCuMK.png" width="512" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Build system information from the logs, we could identify the build language used, the distribution of the OS, Kernel version, etc. For each operating system, Travis CI has a set of default tools defined already. Travis CI will install and configure all the required services required for the build. In this case, Git is installed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AaGPzH7e80uHpMmgj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AaGPzH7e80uHpMmgj.png" width="512" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, the Docker client and server will be installed by default. We can verify the version used by these components in the below screenshot:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AlvXVlgfG8unrvovH.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AlvXVlgfG8unrvovH.png" width="512" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since our build config uses Java JDK, Travis CI will configure the JDK as specified in the travis.yml file and update the JAVA_HOME path variable as appropriate.&lt;/p&gt;

&lt;p&gt;Next, it clones the latest code from the specific branch(master in our example) and updates the current directory. It also reads the environment variables if defined and updates the set-up as needed. Finally, it also checks if there is any build-cache defined for the project. We will discuss more about build cache in the later section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ARZ6kgiolmDFYpOSj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ARZ6kgiolmDFYpOSj.png" width="512" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before pointing our tests to a remote server, we should have a browser configured on a specific port and listen for the incoming requests. From our example, we have configured the RemoteWebDriver as below for launching our tests in Chrome.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;case GRID_CHROME:
                ChromeOptions chromeOptions = new ChromeOptions();
                chromeOptions.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
                try {
                    driver = new RemoteWebDriver(new URL(gridHubURL), chromeOptions);
                } catch (MalformedURLException e) {
                    logger.error("Grid Hub URL is malformed: {}", e.getMessage());
                }
                break;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you remember the travis.yml file in our project, we have a before_script stage defined, and we have already added the below two commands.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- docker run -d -p 4444:4444 -v /dev/shm:/dev/shm selenium/standalone-firefox:4.0.0-rc-1-prerelease-20210618
- docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let’s understand the commands that we have used.&lt;/p&gt;

&lt;p&gt;The first one is the Docker run command that starts the Selenium Firefox container on port 4444.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;docker&lt;/strong&gt;: Docker is the base command for its CLI&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;run&lt;/strong&gt;: Runs the commands in a new container&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-d&lt;/strong&gt;: Command option for Docker run to run the container in the background&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-p&lt;/strong&gt;: Command option for Docker run to publish a container’s port to the host port. Here we are mapping the 4444 port of the container to the 4444 port in the host. The format is host port: container port&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-v&lt;/strong&gt;: Command option for Docker run to bind mount a volume. Here we are using the shared memory /dev/shm in the container and mapping it to the shared memory /dev/shm of the host.&lt;/p&gt;

&lt;p&gt;Next is the image that we are using to run the docker command. Here we are using the Selenium Firefox standalone image with tag 4.0.0-rc-1-prerelease-20210618. More information about the latest versions available can be found from the official Selenium Github repository and the Docker hub public registry.&lt;/p&gt;

&lt;p&gt;Using the below command, Travis CI pulls the specified Selenium Firefox image from the Docker registry and starts creating a new container with the provided configuration. Once it has successfully created a container, we can see the list of the running containers using the second command:&lt;/p&gt;

&lt;p&gt;docker ps&lt;/p&gt;

&lt;p&gt;As we observe from the job logs, the docker run has been executed successfully, and the running container has been listed with the container ID, image name used, ports mapped between container and host, volumes mounted, and status of the container.&lt;/p&gt;

&lt;p&gt;With this, the required setup is completed for running our tests with Travis CI and Docker. The next step is to start sending the HTTP requests to this container on a specific port. We do this using the Maven command as shown below.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=GRID_FIREFOX -DgridHubURL=http://localhost:4444/wd/hub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here we are using the Maven build command along with TestNG to clean the repository and using the install phase with the command arguments such as the suite file, required browser to use, and the grid URL.&lt;/p&gt;

&lt;p&gt;Since the Firefox container is running in the Travis CI instance on port 4444, we send the test requests to this port on the mentioned URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AZioM0Cn-GRhwI2KC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AZioM0Cn-GRhwI2KC.png" width="512" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the Maven build is started, Travis CI downloads the required dependencies from the Maven central repository for the first time. Since we are using the cache configuration for Maven as below, it uses the cache for subsequent runs.&lt;/p&gt;

&lt;p&gt;Therefore, Travis CI can cache the content for the build so that the build process can be sped up. In order to use this caching feature, we need to set the Build pushed branches to ON in the repository settings.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cache:
  directories:
    - .autoconf
    - $HOME/.m2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once all the tests are executed on the browser which is available in the Docker container, we get the results and the build status as zero(0).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AE-PwKvlwAu81FLJA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AE-PwKvlwAu81FLJA.png" width="512" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have successfully performed our first Selenium test automation with Travis CI and Docker. If the build completes with an exit code as zero(0), it will be treated as passed. For many of us in Selenium test automation, it is required to see the test results to assess the regression suite quality. So we just added a phase in the travis.yml file to deploy the artifacts back to GitHub once the build is completed.&lt;/p&gt;

&lt;p&gt;Since we have used TestNG in our Travis CI and Docker example, we get test execution reports in a clean and precise format in the target folder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AT1TLes-0Ho9CwHGp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AT1TLes-0Ho9CwHGp.png" width="512" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AUNrQiG5JeKIq-E1S.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AUNrQiG5JeKIq-E1S.png" width="512" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are trying to deploy the index.html and emailable-report.html as per the below details.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deploy:
  provider: releases
  api_key: ${api_key}
  skip_cleanup: true
  file: [ "target/surefire-reports/emailable-report.html",
          "target/surefire-reports/index.html" ]
  on:
    all_branches: true
    tags: false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Deploy phase details from the Travis CI build logs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AuvFESKbVqHxx6g6o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AuvFESKbVqHxx6g6o.png" width="512" height="113"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to publish the artifacts to GitHub, we need to create a personal access token from the GitHub developer settings page and add it to the environment variables section of the Travis CI repository. The same variable api_key is used in the deploy phase of our configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AtUdyiqybKOobgrxw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AtUdyiqybKOobgrxw.png" width="512" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AKxdANnvTEZQxTYqb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AKxdANnvTEZQxTYqb.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s all! We are done with running one complete build in Travis CI with Docker. In the Build History section, we can see the whole history of test runs as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AzJzXTu_OWM2ucLZF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AzJzXTu_OWM2ucLZF.png" width="512" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see the deployed artifacts in the Releases section on GitHub as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2APyJ5FZx9logw0rVL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2APyJ5FZx9logw0rVL.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also run the tests in other browsers using the other browser containers. But, first, we need to update the before_install phase with the relevant run command in the travis.yml file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;before_install:
    - docker run -d -p 4445:4444 -v /dev/shm:/dev/shm selenium/standalone-chrome:4.0.0-rc-1-prerelease-20210618
    - docker run -d -p 4446:4444 -v /dev/shm:/dev/shm selenium/standalone-firefox:4.0.0-rc-1-prerelease-20210618
 - docker run -d -p 4447:4444 -v /dev/shm:/dev/shm selenium/standalone-edge:4.0.0-rc-1-prerelease-20210713
    - docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Also need to update the -DgridHubURL in the maven command with a configured host port for each browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;A complete &lt;a href="https://www.lambdatest.com/learning-hub/webdriver?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;webdriver&lt;/a&gt; tutorial that covers what WebDriver is, its features, architecture and best practices.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Docker Compose
&lt;/h2&gt;

&lt;p&gt;In our previous Travis CI and Docker example, we have used Docker standalone images from Selenium and started running our tests in Travis CI with Docker. However, if you would have observed, adding each Docker run command in the travis.yml file is not fool-proof, and we need to update the travis.yml file for all the changes required on the browser end.&lt;/p&gt;

&lt;p&gt;Instead, we could leverage the docker-compose utility tool from Docker itself. We can define all the browser-specific services required in a file called docker-compose.yml file and refer to it in the travis.yml file. It would really help us improve the readability of the build configuration file and separate the browser containers.&lt;/p&gt;

&lt;p&gt;Using docker-compose we can use a single command to activate all the services in a single go. Also, docker-compose files are very easy to write as they also use the YAML syntax. All the services in docker compose can even be stopped with a single command.&lt;/p&gt;

&lt;p&gt;We use the below docker-compose.yml file to define the services.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# To execute this docker-compose yml file use `docker-compose -f docker-compose-v3.yml up`
# Add the `-d` flag at the end for detached execution
# To stop the execution, hit Ctrl+C, and then `docker-compose -f docker-compose-v3.yml down`
version: "3"
services:
  chrome:
    image: selenium/node-chrome:4.0.0-rc-1-prerelease-20210618
    volumes:
      - /dev/shm:/dev/shm
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
    ports:
      - "6900:5900"

  edge:
    image: selenium/node-edge:4.0.0-rc-1-prerelease-20210618
    volumes:
      - /dev/shm:/dev/shm
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
    ports:
      - "6901:5900"

  firefox:
    image: selenium/node-firefox:4.0.0-rc-1-prerelease-20210618
    volumes:
      - /dev/shm:/dev/shm
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
    ports:
      - "6902:5900"

  selenium-hub:
    image: selenium/hub:4.0.0-rc-1-prerelease-20210618
    container_name: selenium-hub
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So now the new travis.yml configuration looks as below. Update the travis.yml file in the project with this file, and commit and push the code to start the new build in Travis CI and Docker using the new build configuration.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist: trusty
language: java

jdk:
  - oraclejdk8

before_script:
  - curl https://gist.githubusercontent.com/rakesh-vardan/c1dcf6531b826fad91f18c285d566a71/raw/ad90a18fe5e70f2d6aea06621b76d6e0329a4aab/docker-compose-sel.yml &amp;gt; docker-compose.yaml
  - docker-compose up -d
  - docker-compose ps

script:
  - mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=GRID_FIREFOX -DgridHubURL=http://localhost:4444/wd/hub

cache:
  directories:
    - .autoconf
    - $HOME/.m2

before_script:
  - curl https://gist.githubusercontent.com/rakesh-vardan/c1dcf6531b826fad91f18c285d566a71/raw/ad90a18fe5e70f2d6aea06621b76d6e0329a4aab/docker-compose-sel.yml &amp;gt; docker-compose.yaml
  - docker-compose up -d
  - docker-compose ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The only change here is that in the before_script phase, we are using docker-compose instead of running the direct docker commands. Instead, we use the curl utility to download the docker-compose file and save the content to a file named docker-compose.yml.&lt;/p&gt;

&lt;p&gt;Once that is completed, we use the docker-compose up -d statement to start all the services. This command starts all the services in the compose file and starts listening to the requests on the mentioned ports. Then we use the docker-compose ps command to see the services that are started. Finally, we use the same maven command to point our tests and execute them using the Travis CI build job.&lt;/p&gt;

&lt;p&gt;The below is the screenshot of the Travis CI logs, which shows that the docker-compose has successfully started the defined services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ADck7xfXF1lvcHd8a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ADck7xfXF1lvcHd8a.png" width="512" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Build log details while running the tests on the Chrome browser with the below maven command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=GRID_CHROME -DgridHubURL=http://localhost:4444/wd/hub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AKDXQbJ0bARbvE3PE.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AKDXQbJ0bARbvE3PE.png" width="512" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Build log details while running the tests on the Firefox browser with the below maven command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=GRID_FIREFOX -DgridHubURL=http://localhost:4444/wd/hub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AAczKyF0JXJR5tBor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AAczKyF0JXJR5tBor.png" width="512" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you have observed, we are using the same port for running the tests in Chrome and Firefox browsers. It is because we are leveraging the hub-node architecture of the Selenium Grid here. In our earlier Travis CI and Docker example, where we are running the stand-alone container, we haven’t used the hub container.&lt;/p&gt;

&lt;p&gt;To run the tests with Travis CI and Docker on Selenium Grid 4 architecture, please read our blog on &lt;a href="https://www.lambdatest.com/blog/selenium-grid-4-tutorial-for-distributed-testing/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium Grid 4 Tutorial For Distributed Testing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Perform browser automation testing on the most powerful cloud infrastructure. Leverage LambdaTest &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;automated testing&lt;/a&gt; for faster, reliable and scalable experience on cloud.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Run Selenium Tests With Zalenium And Travis CI
&lt;/h2&gt;

&lt;p&gt;As per our previous examples of using Selenium, Travis CI, Docker images to run the tests, we can clearly see that we always need to update the versions as and when a new version is out. This becomes an overhead, as we need to spend a lot of time updating the configurations.&lt;/p&gt;

&lt;p&gt;If you search for an alternative, you might come across a solution called Zalenium. Zalenium is a flexible and scalable container-based Selenium Grid with video recording, live preview, basic auth &amp;amp; dashboard. It provides all the latest versions of browser images, drivers, and tools required for Selenium test automation. It also has a provision to send the test requests to a third-party cloud provider if the browser requested is not available in the setup.&lt;/p&gt;

&lt;p&gt;Let’s see how we can use them together using Docker images and with Docker compose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Docker Images
&lt;/h2&gt;

&lt;p&gt;In order to use Zalenium, we need to pull the two images as specified below. Once those images are available, start the container using the Docker run command with the necessary options.&lt;/p&gt;

&lt;p&gt;Use the below travis.yml file to configure the build using Docker images for Zalenium.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist: trusty
language: java

jdk:
  - oraclejdk8

before_script:
  - docker pull elgalu/selenium
  - docker pull dosel/zalenium
  - docker run -d --name zalenium -p 4444:4444 -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/videos:/home/seluser/videos --privileged dosel/zalenium start
  - docker ps

script:
  - mvn clean install -DsuiteXmlFile=${suiteXmlFile} -Dbrowser=${browser} -DgridHubURL=${gridHubURL}

cache:
  directories:
    - .autoconf
    - $HOME/.m2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Also, we have made use of environment variables options available in Travis CI to dynamically pass the values at run time for TestNG XML file name, browser, and grid hub URL. We can set these values as below in the Settings section of the project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AWI0G12g0SkYqoapG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AWI0G12g0SkYqoapG.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the execution is started, we can observe in the logs that the Travis CI system has read the environment variables and passed them to the running build.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AhMnomdy-RVPVOxWC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AhMnomdy-RVPVOxWC.png" width="512" height="105"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, the required Docker images are pulled from the central registry, and the Docker run command runs. Finally, the command docker ps shows the running containers at the moment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AJtE_uwpB9ManOtcg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AJtE_uwpB9ManOtcg.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The required browser container is started on port 4444, and the tests will be executed successfully. We can see the test execution status as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AsxrBdDvtbvciam_d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AsxrBdDvtbvciam_d.png" width="512" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly, we can change the browser value to GRID_FIREFOX and trigger a new build.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2An_ha1XJKrPVw5lgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2An_ha1XJKrPVw5lgb.png" width="512" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the execution for GRID_FIREFOX is started, the Travis CI system will read the environment variables and pass them to the running build.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ANFhFE_kgzuy5jovy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ANFhFE_kgzuy5jovy.png" width="512" height="102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The required browser container is started on port 4444, and the tests will be executed successfully. We can see the test execution status as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A7hJa5eTyJ7tGx0ix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A7hJa5eTyJ7tGx0ix.png" width="512" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Docker Compose
&lt;/h2&gt;

&lt;p&gt;We can also leverage Docker compose and Zalenium here to quickly spin up a scalable container-based Selenium Grid and run our tests.&lt;/p&gt;

&lt;p&gt;The below is the docker-compose.yml file with the required services. Here we are starting two services, Selenium and Zalenium, and listening to the incoming requests on port 4444.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Usage:
#   docker-compose up --force-recreate
version: '2.1'

services:
  #--------------#

  dep:
    image: "elgalu/selenium"
    container_name: selenium
    command: echo 0
    restart: "no"

  zalenium:
    image: "dosel/zalenium"
    container_name: zalenium
    hostname: zalenium
    tty: true
    volumes:
      - /tmp/videos:/home/seluser/videos
      - /var/run/docker.sock:/var/run/docker.sock
      - /usr/bin/docker:/usr/bin/docker
    ports:
      - 4444:4444
    depends_on:
      - dep
    command: &amp;gt;
      start --desiredContainers 2
            --maxDockerSeleniumContainers 8
            --screenWidth 800 --screenHeight 600
            --timeZone "Europe/Berlin"
            --videoRecordingEnabled true
            --lambdaTestEnabled false
            --startTunnel false
    environment:
      - HOST_UID
      - HOST_GID
      - PULL_SELENIUM_IMAGE=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The complete travis.yml file, in this case, is as below.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist: trusty
language: java

jdk:
  - oraclejdk8

before_script:
  - curl https://gist.githubusercontent.com/rakesh-vardan/75ab725c9e907772eacb7396383ecd84/raw/4ab799e94cdb9eeaca63528eda97e2d1990f5bc7/docker-compose-zal.yml &amp;gt; docker-compose.yml
  - docker-compose up -d --force-recreate
  - docker-compose ps

script:
  - mvn clean install -DsuiteXmlFile=${suiteXmlFile} -Dbrowser=${browser} -DgridHubURL=${gridHubURL}

cache:
  directories:
    - .autoconf
    - $HOME/.m2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once the build has started, we can see the log details as below. After that, required services will be started, and the tests are executed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AAcp3ZSJa7bie5XAu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AAcp3ZSJa7bie5XAu.png" width="512" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Run Selenium Tests With Selenium Cloud using Travis CI
&lt;/h2&gt;

&lt;p&gt;From all our previous examples, it is evident that we can use Travis CI, Docker, and Selenium together to create automation regression pipelines with ease. As per our requirement, we can configure the declarative YAML files — travis.yml &amp;amp; docker-compose.yml as per our requirement, trigger the build, and get the results. However, there is one drawback with all our previous examples.&lt;/p&gt;

&lt;p&gt;Let’s say if we want to see the regression execution live as it is happening, it is not possible, at least in the community version of Travis CI. On the enterprise version, along with some additional configuration, we could achieve this. Also, if we wanted to check the logs — driver logs, network logs, etc.-. we have to make changes to our examples that required additional effort again. Is there a solution to this problem? The answer is YES! We have LambdaTest cloud-based Selenium grid to our rescue.&lt;/p&gt;

&lt;p&gt;LambdaTest is a &lt;a href="https://www.lambdatest.com/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;cross browser testing&lt;/a&gt; cloud platform to perform automation testing on 3000+ combinations of real browsers and operating systems. It is very easy to configure a project using LambdaTest and start leveraging the benefits out of it. Let’s integrate our project examples with the LambdaTest cloud grid and see how it’s working.&lt;/p&gt;

&lt;p&gt;We try to understand both options — using Docker images and starting the services using the docker-compose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Docker Images
&lt;/h2&gt;

&lt;p&gt;To start with the LambdaTest, first, navigate to the &lt;a href="https://accounts.lambdatest.com/register?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;LambdaTest registration page&lt;/a&gt; and sign-up for a new account. Once the LambdaTest account is activated, go to the &lt;a href="https://accounts.lambdatest.com/login?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Profile&amp;gt;&lt;/a&gt; section and note the LambdaTest Username and LambdaTest Access key. We will need these LambdaTest Username and Access keys to execute our tests on the LambdaTest platform.&lt;/p&gt;

&lt;p&gt;We use the below travis.yml file to run our tests with Travis CI and Docker on the LambdaTest cloud grid.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist: trusty
language: java

jdk:
  - oraclejdk8

before_script:
  - docker pull elgalu/selenium
  - docker pull dosel/zalenium
  - docker run -d --name zalenium -p 4444:4444 -e LT_USERNAME=${LT_USERNAME} -e LT_ACCESS_KEY=${LT_ACCESS_KEY} -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/videos:/home/seluser/videos --privileged dosel/zalenium start --lambdaTestEnabled true
  - docker ps

script:
  - mvn clean install -DsuiteXmlFile=${suiteXmlFile} -Dbrowser=${browser} -DgridHubURL=${gridHubURL}

cache:
  directories:
    - .autoconf
    - $HOME/.m2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Before triggering the build, we need to ensure that the below environment variables are set in the project settings in Travis CI.&lt;/p&gt;

&lt;p&gt;LT_USERNAME - Username from the LambdaTest profile page.&lt;/p&gt;

&lt;p&gt;LT_ACCESS_KEY - Access key obtained from the LambdaTest profile page.&lt;/p&gt;

&lt;p&gt;Below should be the form of gridHubURL.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://&amp;lt;username&amp;gt;:&amp;lt;accessKey&amp;gt;@hub.lambdatest.com/wd/hub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Where is the Username, is the Access key from LambdaTest account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AgJDy5jV0RYOFIqGi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AgJDy5jV0RYOFIqGi.png" width="512" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the build starts, Travis CI reads the configured environment variables.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AdeykJ-FjB2PrMN-b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AdeykJ-FjB2PrMN-b.png" width="512" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As per the travis.yml file configuration, the respective Docker images are pulled, and containers are started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AUsH_37mY0osEKecI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AUsH_37mY0osEKecI.png" width="512" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are using the Docker run command with the flag lambdatestEnabled as true. Because of this, Zalenium starts the hub on port 4444 and one custom node using docker-selenium. A cloud proxy node is registered to the grid since we enabled the cloud integration with the LambdaTest platform. Once the test request is received, it will be sent to the available node with all the capabilities to execute the tests.&lt;/p&gt;

&lt;p&gt;Once Travis CI completes the Selenium test automation execution, we can navigate to the &lt;a href="https://automation.lambdatest.com/timeline/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Automation dashboard&lt;/a&gt; of LambdaTest to see our test execution in the Timeline view. Click on the test case; we would be navigated to the Automation logs screen to see other details such as execution recording, logs, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AOD2c7YIeQxt8bOY8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AOD2c7YIeQxt8bOY8.png" width="512" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AClfyj8iiY1jErace.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AClfyj8iiY1jErace.png" width="512" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, let’s do the same using the docker-compose.&lt;/p&gt;

&lt;p&gt;Refer to our documentation for more details on &lt;a href="https://www.lambdatest.com/support/docs/zalenium-integration-with-lambdatest/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Zalenium integration with LambdaTest&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Docker Compose
&lt;/h2&gt;

&lt;p&gt;It’s pretty much the same as our previous examples with minor modifications. Here is the docker-compose.yml file we use to integrate our tests with the LambdaTest cloud grid.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Usage:
#   docker-compose up --force-recreate
version: '2.1'

services:
  #--------------#

  dep:
    image: "elgalu/selenium"
    container_name: selenium
    command: echo 0
    restart: "no" # ensures it does not get recreated

  zalenium:
    image: "dosel/zalenium"
    container_name: zalenium
    hostname: zalenium
    tty: true
    volumes:
      - /tmp/videos:/home/seluser/videos
      - /var/run/docker.sock:/var/run/docker.sock
      - /usr/bin/docker:/usr/bin/docker
    ports:
      - 4445:4444
    depends_on:
      - dep
    command: &amp;gt;
      start --desiredContainers 2
            --maxDockerSeleniumContainers 8
            --screenWidth 800 --screenHeight 600
            --timeZone "Europe/Berlin"
            --videoRecordingEnabled true
            --lambdaTestEnabled true
            --startTunnel false
    environment:
      - HOST_UID
      - HOST_GID
      - LT_USERNAME=${LT_USERNAME}
      - LT_ACCESS_KEY=${LT_ACCESS_KEY}
      - PULL_SELENIUM_IMAGE=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The configuration is almost similar to previous Travis CI and Docker examples, except that we are configuring the lambdatestEnabled flag to true for the start command. And adding the environment variables for LambdaTest username and access keys using LT_USERNAME and LT_ACCESSKEY. Also, please make sure that the environment variables in the Travis CI project are still intact and available during the build.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist: trusty
language: java

jdk:
  - oraclejdk8

before_script:
  - curl https://gist.githubusercontent.com/rakesh-vardan/f23ab04fe12512dc6f8ceb20d738f1ad/raw/736edd8a8e7f7276535e253a688e6625cdfd7abb/docker-compose-zel.yml &amp;gt; docker-compose.yml
  - docker-compose up -d --force-recreate
  - docker-compose ps

script:
  - mvn clean install -DsuiteXmlFile=${suiteXmlFile} -Dbrowser=${browser} -DgridHubURL=${gridHubURL}

cache:
  directories:
    - .autoconf
    - $HOME/.m2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ADdcQaHJnWC597HaN.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ADdcQaHJnWC597HaN.png" width="512" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The build result would be similar as the services are created by docker-compose, and the test execution happens on the browser containers in LambdaTest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Which are the most wanted &lt;a href="https://www.lambdatest.com/blog/automation-testing-tools/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;automated testing tools&lt;/a&gt; that have climbed the top of the ladder so far? Let’s take a look.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Parallel Testing With Travis CI, Docker And LambdaTest
&lt;/h2&gt;

&lt;p&gt;Till now, we have been discussing running the Selenium UI tests sequentially using multiple options with Travis CI, Docker, and LambdaTest. But as the application enhances we will have more tests in the testing suite. And as the size of the testing suite is big, the time it takes to execute will also be more.&lt;/p&gt;

&lt;p&gt;If the execution time is more than we are not meeting the primary goal of test automation, we need to provide early feedback on the product quality to the development team. So how do we achieve this goal without compromising on the testing scope?&lt;/p&gt;

&lt;p&gt;The answer is to run the tests in parallel mode wherever feasible to reduce the execution time drastically.&lt;/p&gt;

&lt;p&gt;Coming back to our discussion, let us make some changes to the testng.xml file as below to support parallel test execution. Add the required changes in a new file called testng-parallel.xml and add them to our project. We are using the parallel attribute of testNG with a value of tests and configuring the tests to run in parallel with a thread count of 2. As you observe, we are configuring the file to run our tests in Chrome and Firefox browsers from the LambdaTest cloud platform.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"&amp;gt;
&amp;lt;suite name="All Test Suite in parallel" parallel="tests" thread-count="2"&amp;gt;
    &amp;lt;test verbose="2" name="travisci-selenium-docker-lambdatest"&amp;gt;
        &amp;lt;parameter name="browser" value="GRID_LAMBDATEST_CHROME"/&amp;gt;
        &amp;lt;classes&amp;gt;
            &amp;lt;class name="com.lambdatest.SeleniumTests"&amp;gt;
            &amp;lt;/class&amp;gt;
        &amp;lt;/classes&amp;gt;
    &amp;lt;/test&amp;gt;
    &amp;lt;test verbose="2" name="travisci-selenium-docker-lambdatest1"&amp;gt;
        &amp;lt;parameter name="browser" value="GRID_LAMBDATEST_FIREFOX"/&amp;gt;
        &amp;lt;classes&amp;gt;
            &amp;lt;class name="com.lambdatest.SeleniumTests"&amp;gt;
            &amp;lt;/class&amp;gt;
        &amp;lt;/classes&amp;gt;
    &amp;lt;/test&amp;gt;
&amp;lt;/suite&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There are many approaches to running parallel tests using TestNG configuration.&lt;/p&gt;

&lt;p&gt;Refer to our detailed blog on configuring &lt;a href="https://www.lambdatest.com/blog/create-testng-xml-file-execute-parallel-testing/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;TestNG XML and execute parallel testing&lt;/a&gt; with detailed explanations.&lt;/p&gt;

&lt;p&gt;In order to support the parallel test execution, we need to make the below changes to our .travis.yml file. Here we are using the Zalenium Docker along with LambdaTest to set up our test execution infrastructure.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dist: trusty
language: java

jdk:
  - oraclejdk8

before_script:
  - docker pull elgalu/selenium
  - docker pull dosel/zalenium
  - docker run -d --name zalenium -p 4444:4444 -e LT_USERNAME=${LT_USERNAME} -e LT_ACCESS_KEY=${LT_ACCESS_KEY} -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/videos:/home/seluser/videos --privileged dosel/zalenium start --lambdaTestEnabled true
  - docker ps

script:
  - mvn clean install -DsuiteXmlFile=${suiteXmlFile} -DgridHubURL=${gridHubURL}

cache:
  directories:
    - .autoconf
    - $HOME/.m2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The maven command used to run the tests is as below. We are passing the suite file and the grid URL from the environment variables of Travis CI.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mvn clean install -DsuiteXmlFile=${suiteXmlFile} -DgridHubURL=${gridHubURL}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And the configuration for the job within the Travis CI platform is as below. We are defining the environment variables required for our test execution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AuEYjL7GPOOeXUYcg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AuEYjL7GPOOeXUYcg.png" width="512" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once these values are set, let’s start our job in Travis CI. After the job is completed successfully, we can see the job log as below. We have added logger statements to our code in the test methods to print the currently used thread id.&lt;/p&gt;

&lt;p&gt;Hence from the log, we can see that TestNG creates two threads, and the tests are distributed across them. And a total of 10 tests are executed successfully, five on chrome browser and five on firefox browser in LambdaTest cloud grid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AQtJPGrXEMzCDWihl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AQtJPGrXEMzCDWihl.png" width="512" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we go back to our LambdaTest automation dashboard, we can observe that two sessions are started as the job is executed. One session is for a chrome browser and one for a firefox browser. Also, we can observe that we are using 2 of 5 parallel sessions in the LambdaTest platform — which indicates that our tests are being executed in parallel mode.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AogZOfadGDrp0emVq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AogZOfadGDrp0emVq.png" width="512" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Like this, we could play around with configurations available in TestNG, Docker, and LambdaTest and build efficient and robust Selenium test automation suites.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this post, we have covered some of the important concepts in Travis CI and Docker to build the pipelines for performing the Selenium test automation. We have also discussed integrating our test suites with the LambdaTest cloud grid and leveraging it in our Selenium test automation efforts. and &lt;a href="https://www.lambdatest.com/blog/how-professional-qa-implements-a-robust-ci-cd-pipeline/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;build robust CI/CD pipelines&lt;/a&gt; using Travis CI, Docker, and LambdaTest. There are many more exciting features that you can try upon and explore.&lt;/p&gt;

&lt;p&gt;Let us know in the comments if you want to have another article on the same topic with advanced capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Testing and Travis-ci-ing!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>testing</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building Automated Testing Pipeline With Semaphore CI And Selenium Grid</title>
      <dc:creator>RakeshVardhan1</dc:creator>
      <pubDate>Wed, 23 Nov 2022 15:33:05 +0000</pubDate>
      <link>https://dev.to/testmuai/building-automated-testing-pipeline-with-semaphore-ci-and-selenium-grid-44ea</link>
      <guid>https://dev.to/testmuai/building-automated-testing-pipeline-with-semaphore-ci-and-selenium-grid-44ea</guid>
      <description>&lt;p&gt;In today’s digital age, product teams must build products at a brisk pace while maintaining the best quality. Therefore, the methodology to follow and the tool selection to accomplish this can be paramount to get better results. Moreover, software applications don’t just support businesses now; rather, they have become an integral part of a business. Hence, it’s obvious that the product teams deliver a product with speed, reliability, scale, security, quality, and improved collaboration. So companies started following the DevOps model, which is a combination of Development (Dev) and Operations (Ops) teams.&lt;/p&gt;

&lt;p&gt;DevOps include the practices such as &lt;a href="https://www.lambdatest.com/blog/what-is-continuous-integration-and-continuous-delivery/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Continuous Integration and Continuous Delivery&lt;/a&gt; (CI/CD), Developing Microservices, Adopting Infrastructure as code, Monitoring and Logging the application, and Communication &amp;amp; collaboration within teams. To rapidly develop a product with speed, teams often use SaaS (Software as a Service) solutions that are available to accomplish the required task without the overhead of setting up or maintaining any infrastructure. One such solution available in the market for CI/CD is Semaphore CI.&lt;/p&gt;

&lt;p&gt;In this article, we’ll learn about Semaphore Continuous Integration and dig deeper into using it for building automated testing pipelines with &lt;a href="https://www.lambdatest.com/selenium-grid-online?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;online Selenium Grid&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s begin!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;A complete &lt;a href="https://www.lambdatest.com/learning-hub/webdriver?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;webdriver&lt;/a&gt; tutorial that covers what WebDriver is, its features, architecture and best practices.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview Of Semaphore CI
&lt;/h2&gt;

&lt;p&gt;Semaphore CI is one of the few CI/CD tools available to accomplish continuous integration and continuous delivery. Other &lt;a href="https://www.lambdatest.com/blog/best-ci-cd-tools/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;best CI/CD tools&lt;/a&gt; in the same space are Jenkins, Azure DevOps, TravisCI, CircleCI, TeamCity Cloud, etc. Semaphore Continuous Integration tool identifies itself as the hosted CI/CD solution for teams that do not have bottlenecks! It is designed and built around increasing developer productivity and reducing the execution time for any pipeline. As per the official website, Semaphore Continuous Integration is the fastest CI/CD solution available in the market, with the ability to deliver the projects in record time.&lt;/p&gt;

&lt;p&gt;Refer below to the benchmarking performance of Semaphore CI for a production-grade web application as compared to other CI/CD tools:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A8ii2AgylaHpen4At.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A8ii2AgylaHpen4At.png" width="512" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the above survey, it is clear that the Semaphore CI is the winner in terms of shorter execution time, as it has taken the least amount of time to complete operations in the pipeline.&lt;/p&gt;

&lt;p&gt;Now you have understood what Semaphore Continuous Integration is, let’s see some of the best features available in Semaphore Continuous Integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features Of Semaphore CI
&lt;/h2&gt;

&lt;p&gt;Below are some of the important features provided by the Semaphore Continuous Integration tool.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Hosted CI solution, no need to manage external servers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flexibility to build from simple sequential build to multi-stage parallel programmable pipelines&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flexibility to create our environment with native Docker support&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optimize the monorepo workflows&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build, test and deploy on different programming languages and platforms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Faster builds with smart caching&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support for containerization for pipelines using Docker and Kubernetes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ability to debug the failures in seconds by implementing SSH into the running jobs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support for all deployment strategies — canary, blue-green, etc. including the option to rollback changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Built-in Docker registry to store the images.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before we get into the details of Semaphore CI, let’s brush up on some important concepts around CI/CD. The below video will deep dive into the fundamentals of Continuous Integration, Continuous Deployment, and Continuous Delivery(CI/CD).&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/MggFYkomfx0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;However, you can also visit the &lt;a href="https://www.youtube.com/c/LambdaTest?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;LambdaTest YouTube channel&lt;/a&gt; for videos that will guide you through building an automated testing pipeline using popular CI/CD tools like Jenkins, GitLab, CircleCI, and more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Mobile &lt;a href="https://www.lambdatest.com/mobile-emulator-online?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Mobile Emulator Online&lt;/a&gt; from LambdaTest allows you to seamlessly test your mobile applications, websites, and web apps on mobile browsers and mobile devices.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started With Semaphore CI
&lt;/h2&gt;

&lt;p&gt;Semaphore Continuous Integration is a commercial CI/CD service offering. It offers three pricing plans for the customers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Free&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Startup&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enterprise Cloud&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Though it’s a commercial product, Semaphore CI has a free plan that provides $10 worth of credits (1300 minutes) for running a single job at a time on Linux, macOS, and Docker environments. We will use this option to explore Semaphore Continuous Integration and learn to build pipelines for our test automation examples using cloud Selenium Grid.&lt;/p&gt;

&lt;p&gt;The basic prerequisite is that “You need an active GitHub account and a code repository”.&lt;/p&gt;

&lt;p&gt;As of now, Semaphore supports creating pipelines for repositories that are hosted on GitHub. However, there is a plan to support repositories in Bitbucket. And supporting other options such as GitLab integration and any git repository is under consideration by the team.&lt;/p&gt;

&lt;p&gt;We are using the Demo GitHub repository to discuss examples.&lt;/p&gt;

&lt;p&gt;Below are the steps to get started using the Semaphore CI&lt;/p&gt;

&lt;p&gt;1- Navigate to Semaphore CI official website and click on the Sign up with GitHub button.&lt;/p&gt;

&lt;p&gt;2- Semaphore CI will open up in a new tab. Click on Continue with GitHub button.&lt;/p&gt;

&lt;p&gt;3- It takes us to the GitHub authorization page. Authorize the app by clicking on Authorize renderedtext.&lt;/p&gt;

&lt;p&gt;4- On the next screen, Semaphore asks you to create an organization. By default, it takes the GitHub username and creates a Semaphore URL for us.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A94OkDM9j1Vmg_0o0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A94OkDM9j1Vmg_0o0.png" width="512" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5- Click on Save &amp;amp; Continue.&lt;/p&gt;

&lt;p&gt;6- On the next screen, choose the plan for your organization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AAU6ZNr5eiBNWcHoe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AAU6ZNr5eiBNWcHoe.png" width="512" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;7- We can choose either of the options here. Even for the Pro option, we don’t need to enter any credit card details.&lt;/p&gt;

&lt;p&gt;8- Once this is completed, we can see our newly configured organization as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A4ngs-7jXbfwg26Ds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A4ngs-7jXbfwg26Ds.png" width="512" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;9- Upon clicking on the organization tile, we could see our workspace as below. We could see all of the work that we have been doing in the organization. Since I have already created some pipelines earlier, we can see all these details. If you are creating it for the first time, you can see an option to set up a new project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AR2Obu-MsU3ePiuDy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AR2Obu-MsU3ePiuDy.png" width="512" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;10- Click on the Create New button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A91ZTBrdWCm3DPPr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A91ZTBrdWCm3DPPr2.png" width="512" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose the repository you want to work with. We can either choose the GitHub app or use a GitHub personal token. Let’s select the project and click on Choose.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AGhnulfk8dp6qsy9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AGhnulfk8dp6qsy9w.png" width="512" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;11- Semaphore initializes the set-up required as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AJgTaEnKBwmoGXSb9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AJgTaEnKBwmoGXSb9.png" width="512" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;12- We can add collaborators required for the project in the Add People or go to the next page.&lt;/p&gt;

&lt;p&gt;13- In the Setup workflow, choose the Single Job workflow and click on Looks good, let’s start button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AsfOcRXcyfYw6qDia.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AsfOcRXcyfYw6qDia.png" width="512" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;14- Once done, Semaphore Continuous Integration starts the pipeline and executes the jobs inside the pipeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2At218nurytIDFONLv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2At218nurytIDFONLv.png" width="512" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s it! This is the entire process of setting up a new account with Semaphore Continuous Integration and creating a new sample pipeline.&lt;/p&gt;

&lt;p&gt;In the next section, let’s understand some important concepts and terminology used in Semaphore Continuous Integration and then build new workflows and pipelines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;In this article, we look at what &lt;a href="https://www.lambdatest.com/blog/regression-testing-what-is-and-how-to-do-it/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Regression testing&lt;/a&gt; is, its importance and types, and how to perform it.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Important Concepts In Semaphore CI
&lt;/h2&gt;

&lt;p&gt;Similar to other CI/CD solutions, Semaphore Continuous Integration has its own set of terminology while working with pipelines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Workflow&lt;/strong&gt;: Workflow in Semaphore CI is similar to a &lt;a href="https://www.lambdatest.com/blog/jenkins-pipeline-tutorial/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Jenkins Pipeline&lt;/a&gt;. Semaphore uses pipelines, blocks, tasks, and promotions in the workflow to manage the application CI process. Each workflow for a project can have multiple pipelines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pipeline&lt;/strong&gt;: A pipeline is a collection of similar blocks within the same workflow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Block&lt;/strong&gt;: Blocks are the building components of a pipeline. Each block in Semaphore CI consists of an optional name and task as a mandatory value. Blocks define steps in the pipeline on what to do as part of the pipeline. By default, all the blocks in the pipeline run sequentially by Semaphore CI. However, we can also define blocks to run in parallel mode by using block dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Task&lt;/strong&gt; (Mandatory): Task specifies what to do in the block. The task consists of jobs, epilogue, prologue, and secrets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Job&lt;/strong&gt;: Jobs in the Semaphore specify the commands to execute in a pipeline. Each job is run in an isolated clean virtual environment created by the Semaphore. Examples include checking out the code, running tests using Maven, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Promotion&lt;/strong&gt;: Promotions in Semaphore are the junction blocks used for deployment purposes and promoting builds to different environments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Secret&lt;/strong&gt;: Secrets in Semaphore are used to store sensitive information for a workflow such as API keys, passwords, etc., which are not committed to the version control system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent&lt;/strong&gt;: Virtual environment to run the workflows is created by Semaphore, post which it is ready for us to use. These machines are called agents. They perform the actual execution of the job. Each agent consists of a machine type and OS image used to build the agent. Semaphore supports agents on Linux and macOS environments.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The below picture from the official Semaphore documentation gives a high-level overview of these concepts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ApzfyeGUYYkfpP5t0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ApzfyeGUYYkfpP5t0.png" width="512" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Test your website or web app online for iOS browser compatibility. Perform seamless cross browser testing on the latest &lt;a href="https://www.lambdatest.com/test-on-iphone-simulator?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;iPhone tester&lt;/a&gt;. Try for free!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building A Pipeline With Semaphore CI
&lt;/h2&gt;

&lt;p&gt;If you have noticed in the getting started section, Semaphore has created a new branch called setup-semaphore and added a configuration file semaphore.yml in the .semaphore directory in our project. Basically, the idea here is to create a pull request to the master/main branch from the setup-semaphore branch once all the pipeline steps are defined.&lt;/p&gt;

&lt;p&gt;Based on the pull request trigger, which is configured by default, Semaphore starts the workflow and executes the jobs within the pipeline.&lt;/p&gt;

&lt;p&gt;We have created the pull request to master and we will be working in the master branch only for all our examples.&lt;/p&gt;

&lt;p&gt;There are two options available to create a new workflow in Semaphore.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Using the Visual Builder&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using the declarative YAML configuration in semaphore.yml&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let us first start configuring our workflow using the Visual Builder. But, before that, let’s try to understand the test scenario that we are trying to configure in Semaphore Continuous Integration.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open a specified browser.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open the GitHub page and verify the title.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open the Gmail page and verify the title.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open the LambdaTest page and verify the title.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We have set up our &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium automation&lt;/a&gt; project and TestNG to run the tests in any browser. We use the BrowserFactory and BaseTest to instantiate the browser based on the input and pass it on to our tests. Please refer to the Demo GitHub repository for complete project code.&lt;/p&gt;

&lt;p&gt;We are using TestNG and adding appropriate annotations for our tests. We have also configured the testng.xml file to include what tests to run.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"&amp;gt;
&amp;lt;suite name="All Test Suite"&amp;gt;
    &amp;lt;test verbose="2" name="firefox tests"&amp;gt;
        &amp;lt;parameter name="browser" value="LOCAL_FIREFOX"/&amp;gt;
        &amp;lt;parameter name="gridHubURL" value="http://localhost:4444/wd/hub"/&amp;gt;
        &amp;lt;classes&amp;gt;
            &amp;lt;class name="org.lambdatest.FirstTest"/&amp;gt;
            &amp;lt;class name="org.lambdatest.SecondTest"/&amp;gt;
        &amp;lt;/classes&amp;gt;
    &amp;lt;/test&amp;gt;
&amp;lt;/suite&amp;gt;

&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;
&amp;lt;!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"&amp;gt;
&amp;lt;suite name="All Test Suite"&amp;gt;
    &amp;lt;test verbose="2" name="firefox tests"&amp;gt;
        &amp;lt;parameter name="browser" value="LOCAL_FIREFOX"/&amp;gt;
        &amp;lt;parameter name="gridHubURL" value="http://localhost:4444/wd/hub"/&amp;gt;
        &amp;lt;classes&amp;gt;
            &amp;lt;class name="org.lambdatest.FirstTest"/&amp;gt;
            &amp;lt;class name="org.lambdatest.SecondTest"/&amp;gt;
        &amp;lt;/classes&amp;gt;
    &amp;lt;/test&amp;gt;
&amp;lt;/suite&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Finally, we will use the below maven command to trigger the tests.&lt;/p&gt;

&lt;p&gt;mvn clean install -DsuiteXmlFile=testng.xml&lt;/p&gt;

&lt;p&gt;Complete code for this project is available here on the GitHub repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding A Pipeline With Visual Builder
&lt;/h2&gt;

&lt;p&gt;With all the prerequisites in place, let’s start with our first pipeline using the Visual Builder in the Semaphore CI.&lt;/p&gt;

&lt;p&gt;Go to the organization URL, and open the project that we have imported from GitHub. Select the branch as master and click on the edit workflow button.&lt;/p&gt;

&lt;p&gt;We can see the values below for the pipeline section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Ag_MioIgEV56j9Q0q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Ag_MioIgEV56j9Q0q.png" width="512" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we see here, Semaphore has chosen default values for The Agent, OS Image, and the Machine types. If needed, we can change these values and proceed with creating the Job. If any other steps need to be performed before and after running the pipeline, we can configure the commands in the Prologue and Epilogue sections, respectively.&lt;/p&gt;

&lt;p&gt;For now, let’s take all the default values and change the name to First Pipeline in Semaphore and click on the Job.&lt;/p&gt;

&lt;p&gt;Add a name for the block, give the specified commands in the jobs section and keep other values at their defaults. Here the command checkout is mandatory to clone the repository and create the workspace. The next one is the maven command that we need to run our UI tests in &lt;a href="https://www.lambdatest.com/selenium?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AM7PefZmZMXk1tWc5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AM7PefZmZMXk1tWc5.png" width="512" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on Run the workflow. Semaphore asks to commit the changes to the code repository. Add a comment and click on Looks good, let’s go. Semaphore initiates the workflow and starts executing the job that is configured for our project. As we observe in the below screen, the workflow is in Running status.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AGXSKjgFC-aAs5G6y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AGXSKjgFC-aAs5G6y.png" width="512" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the workflow is completed, we could check the logs as below. Next, the Semaphore starts creating the fresh virtual environment for our job, loads all the required variables, if any, checks out the code from the repository, and runs the build commands specified.&lt;/p&gt;

&lt;p&gt;From the below screen, we could observe that our pipeline execution is successful, and all our tests are passed!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AeI9cqWfBH9qf3Srs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AeI9cqWfBH9qf3Srs.png" width="512" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the summary of the tests that are executed as part of our job.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AlJzxYYggUVlhjXKD.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AlJzxYYggUVlhjXKD.png" width="512" height="126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, the status is updated as Passed at the workflow level.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AriNakxkHZDSF9blH.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AriNakxkHZDSF9blH.png" width="512" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;A complete &lt;a href="https://www.lambdatest.com/learning-hub/webdriver?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=learning_hub" rel="noopener noreferrer"&gt;Webdriver&lt;/a&gt; tutorial that covers what WebDriver is, its features, architecture and best practices.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring A Pipeline With semaphore.yml
&lt;/h2&gt;

&lt;p&gt;In our previous run, we have leveraged the Visual Builder option available in Semaphore CI to add the configuration for the pipeline. However, you can also add the configuration using a declarative YAML file — semaphore.yml&lt;/p&gt;

&lt;p&gt;You have to click on the Edit workflow button and then click on the semaphore.yml file to open the configuration file on the web. We can see the below configuration is automatically available for us. It is because of the configuration we did using the visual builder option in the previous step. Therefore, the same instructions are replicated here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A6eM1S16BpnKvjOOF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A6eM1S16BpnKvjOOF.png" width="512" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s look at the configuration in detail.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;version&lt;/strong&gt; — version refers to the pipeline YAML version used in the configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;name&lt;/strong&gt; — the name of the pipeline&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;agent&lt;/strong&gt; — agent defines the virtual environment, i.e., software and hardware that needs to be created to run our job&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;machine&lt;/strong&gt; — machine property is added to the agent only, and it has two properties — type and os_image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;type&lt;/strong&gt; — virtualized hardware that is available for us to use in jobs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;os_image&lt;/strong&gt; — operating system to be used for the jobs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;blocks&lt;/strong&gt; — blocks define steps in the pipeline on what to do as part of the pipeline&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;task&lt;/strong&gt; — the task is a mandatory property in blocks which refers to the steps needed inside a block&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;env_vars&lt;/strong&gt; — key-value pair that holds the environment variables as part of a job&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;jobs&lt;/strong&gt; — property where we mention the actual commands to be executed along with a name to it&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;commands&lt;/strong&gt; — an array of strings that holds the commands to execute for a job&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we have understood the semaphore.yml configuration let’s discuss the next example. We use the below semaphore.yml file for our next pipeline execution and see if we could run the pipeline in Semaphore Continuous Integration. As you observe, we are running our tests in the Chrome browser this time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Semaphore.yml file&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: v1.0
name: First Pipeline with semaphore
agent:
  machine:
    type: e1-standard-2
    os_image: ubuntu1804
blocks:
  - name: Tests in Chrome
    task:
      prologue:
        commands:
          - checkout
      jobs:
        - name: Run tests
          commands:
            - mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=LOCAL_CHROME
      epilogue:
        always:
          commands:
            - test-results publish target/surefire-reports/junitreports/*.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Some of the new properties are mentioned below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;prologue&lt;/strong&gt; — This is executed before the commands of each job of a task item. In our example, we have added the checkout command to the prologue block to check the source code before our test execution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;epilogue&lt;/strong&gt; — This is executed after the commands of each job item of a task. Semaphore has a beta feature at the moment to publish the test results from the pipeline execution without any additional configuration. However, since we are using TestNG in our example, we get the XML reports post-execution. Hence we configured the XML files as part of the epilogue block to check the execution results in a more readable way.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, we are passing the browser property to the test suite using the below maven command.&lt;/p&gt;

&lt;p&gt;mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=LOCAL_CHROME&lt;/p&gt;

&lt;p&gt;Once the pipeline is executed with the new configuration specified in the semaphore.yml file, we can see the below log. Our execution is successful even in the Chrome browser also!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AVfQsE7ckb27N8H3y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AVfQsE7ckb27N8H3y.png" width="512" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the logs, we could see that the Chrome browser instance is launched.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe3pdx1m5pqm3cvggry0b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe3pdx1m5pqm3cvggry0b.png" width="512" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the tests are executed successfully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A0hInF6eGu6nxRFsF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A0hInF6eGu6nxRFsF.png" width="512" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The workflow view is shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A5eDEg0570Y5pSHAk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A5eDEg0570Y5pSHAk.png" width="512" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please take a look at the expanded logs for the test results publishing command that we specified in the epilogue section. In addition, Semaphore is publishing the JUnit XML results to the summary page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AEWfaUJ2UWIvWqQmP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AEWfaUJ2UWIvWqQmP.png" width="512" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navigate to the Summary tab, and we can see the detailed test execution results there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AjXsd84_7nkZ-PT6r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AjXsd84_7nkZ-PT6r.png" width="512" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If there is a failure in our tests, the view displays below — with the details to easily debug the issue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AvAyF9QI_AoaUH4AM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AvAyF9QI_AoaUH4AM.png" width="512" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AJPqKGtlThNo9jjWw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AJPqKGtlThNo9jjWw.png" width="512" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Perform browser &lt;a href="https://www.lambdatest.com/automation-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=webpage" rel="noopener noreferrer"&gt;Automation testing&lt;/a&gt; on the most powerful cloud infrastructure. Leverage LambdaTest automation testing for faster, reliable and scalable experience on cloud.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building A Complex Workflow With semaphore.yml
&lt;/h2&gt;

&lt;p&gt;With the knowledge that we have acquired till now, we could run the pipelines in the Semaphore Continuous Integration tool. We have discussed using Visual Builder and semaphore.yml to create and run a simple UI test pipeline. How about taking our experience to the next level and creating a complex workflow for our project? Let’s see how we can do it.&lt;/p&gt;

&lt;p&gt;Add the below code in the semaphore.yml file and run the workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Semaphore.yml file for complex flow — sequential&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: v1.0
name: Complex Pipeline with multiple browsers - sequential
agent:
  machine:
    type: e1-standard-2
    os_image: ubuntu1804
blocks:
  - name: Build
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      jobs:
        - name: Build
          commands:
            - checkout
            - mvn -q package -DskipTests=true
            - cache store
  - name: API Smoke tests
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      prologue:
        commands:
          - checkout
          - cache restore
      jobs:
        - name: Run Smoke API tests
          commands:
            - mvn clean install -DsuiteXmlFile=testng-api.xml
      epilogue:
        always:
          commands:
            - test-results publish target/surefire-reports/junitreports/*.xml
  - name: Firefox tests
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      prologue:
        commands:
          - checkout
          - cache restore
      jobs:
        - name: Run tests in Firefox
          commands:
            - mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=LOCAL_FIREFOX
      epilogue:
        always:
          commands:
            - test-results publish target/surefire-reports/junitreports/*.xml
  - name: Chrome tests
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      prologue:
        commands:
          - checkout
          - cache restore
      jobs:
        - name: Run tests in Chrome
          commands:
            - mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=LOCAL_CHROME
      epilogue:
        always:
          commands:
            - test-results publish target/surefire-reports/junitreports/*.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;From the workflow overview page, we could see the below execution summary. First, the project is built, then the API &lt;a href="https://www.lambdatest.com/learning-hub/smoke-testing?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;smoke tests&lt;/a&gt; are executed, then the UI tests are executed in Firefox browser followed by UI test execution in Chrome browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AqD-ViWlu1XpVTolY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AqD-ViWlu1XpVTolY.png" width="512" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are using the env_vars property for storing the maven local repository path. The env_vars property is a key-value pair with the name and value for the variable. Next, we are using the Semaphore CI caching feature to cache and reuse the project dependencies.&lt;/p&gt;

&lt;p&gt;We have used the cache store command to store the cache and cache restore to restore the saved cache. As you have noted, along with our previous UI tests using Selenium, we have added a simple API test as part of our&lt;br&gt;
suite using REST Assured library. And we configured to run the API tests using a separate TestNG XML file — testng-api.xml&lt;/p&gt;

&lt;p&gt;Since we haven’t declared any dependencies between the jobs inside the block, the jobs are executed in sequential order by default one after the other. So let’s tweak our semaphore.yml as below and see if we can run the same in parallel mode.&lt;/p&gt;

&lt;p&gt;Add the below code in the semaphore.yml file and run the workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Semaphore.yml file for complex flow — Parallel&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: v1.0
name: Complex Pipeline with multiple browsers - parallel
agent:
  machine:
    type: e1-standard-2
    os_image: ubuntu1804
blocks:
  - name: Build
    dependencies: []
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      jobs:
        - name: Build
          commands:
            - checkout
            - mvn -q package -DskipTests=true
            - cache store
  - name: API Smoke tests
    dependencies:
      - Build
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      prologue:
        commands:
          - checkout
          - cache restore
      jobs:
        - name: Run Smoke API tests
          commands:
            - mvn clean install -DsuiteXmlFile=testng-api.xml
      epilogue:
        always:
          commands:
            - test-results publish target/surefire-reports/junitreports/*.xml
  - name: Firefox tests
    dependencies:
      - API Smoke tests
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      prologue:
        commands:
          - checkout
          - cache restore
      jobs:
        - name: Run tests in Firefox
          commands:
            - mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=LOCAL_FIREFOX
      epilogue:
        always:
          commands:
            - test-results publish target/surefire-reports/junitreports/*.xml
  - name: Chrome tests
    dependencies:
      - API Smoke tests
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      prologue:
        commands:
          - checkout
          - cache restore
      jobs:
        - name: Run tests in Chrome
          commands:
            - mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=LOCAL_CHROME
      epilogue:
        always:
          commands:
            - test-results publish target/surefire-reports/junitreports/*.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A0IqA7az0xN6nHmit.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A0IqA7az0xN6nHmit.png" width="512" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the workflow overview page, we could see the above test execution summary. First, the project is built, then the API smoke tests are executed. As per the semaphore.yml configuration, we have added API Smoke tests as the dependency for jobs to run Firefox tests and Chrome tests.&lt;/p&gt;

&lt;p&gt;As soon as the API Smoke tests job is completed, Semaphore triggers the other jobs simultaneously (i.e. the UI tests are executed in Firefox browser and Chrome browser simultaneously). This small configuration change enables the execution of the builds in less time and improves the overall efficiency of the pipelines. Therefore, we could achieve parallel execution without any code changes on our project, along with zero changes in testng.xml.&lt;/p&gt;
&lt;h2&gt;
  
  
  Semaphore CI Pipeline With Docker
&lt;/h2&gt;

&lt;p&gt;Till now, we have been running our tests on the browsers launched in the virtual infrastructure created by the Semaphore CI. Semaphore Continuous Integration also has native support to create and run the pipelines using docker. Docker CLI is already installed in all Semaphore virtual machines; hence we can use it without additional configuration. Let’s modify our configuration to run the same pipeline in browser containers launched by docker. Docker is one of the most widely used containerization technologies. To learn more about Docker and execute UI Selenium tests using Docker, please refer to our detailed article on how to &lt;a href="https://www.lambdatest.com/blog/run-selenium-tests-in-docker/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;run Selenium tests in Docker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Add the below code in the semaphore.yml file and run the workflow in docker.&lt;/p&gt;

&lt;p&gt;Semaphore.yml file for complex flow — Docker Containers&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: v1.0
name: Complex Pipeline with multiple browsers - docker
agent:
  machine:
    type: e1-standard-2
    os_image: ubuntu1804
blocks:
  - name: Build
    dependencies: []
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      jobs:
        - name: Build
          commands:
            - checkout
            - mvn -q package -DskipTests=true
            - cache store
  - name: API Smoke tests
    dependencies:
      - Build
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      prologue:
        commands:
          - checkout
          - cache restore
      jobs:
        - name: Run Smoke API tests
          commands:
            - mvn clean install -DsuiteXmlFile=testng-api.xml
      epilogue:
        always:
          commands:
            - test-results publish target/surefire-reports/junitreports/*.xml
  - name: Firefox tests
    dependencies:
      - API Smoke tests
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      prologue:
        commands:
          - checkout
          - cache restore
      jobs:
        - name: Run tests in Firefox
          commands:
            - docker run -d -p 4444:4444 -v /dev/shm:/dev/shm selenium/standalone-firefox:4.0.0-rc-1-prerelease-20210618
            - docker ps
            - mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=GRID_FIREFOX -DgridHubURL=http://localhost:4444/wd/hub
      epilogue:
        always:
          commands:
            - test-results publish target/surefire-reports/junitreports/*.xml
  - name: Chrome tests
    dependencies:
      - API Smoke tests
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      prologue:
        commands:
          - checkout
          - cache restore
      jobs:
        - name: Run tests in Chrome
          commands:
            - docker run -d -p 4444:4444 -v /dev/shm:/dev/shm selenium/standalone-chrome:4.0.0-rc-1-prerelease-20210618
            - docker ps
            - mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=GRID_CHROME -DgridHubURL=http://localhost:4444/wd/hub
      epilogue:
        always:
          commands:
            - test-results publish target/surefire-reports/junitreports/*.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;As you take a look at the semaphore.yml configuration, there are some minor changes that we have made to enable the execution in docker containers. We will use the below docker run commands to spin specific browser containers on port 4444 and point our tests to run on the relevant grid hub URL with maven arguments.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d -p 4444:4444 -v /dev/shm:/dev/shm selenium/standalone-firefox:4.0.0-rc-1-prerelease-20210618

mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=GRID_FIREFOX -DgridHubURL=http://localhost:4444/wd/hub

docker run -d -p 4444:4444 -v /dev/shm:/dev/shm selenium/standalone-chrome:4.0.0-rc-1-prerelease-20210618

mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=GRID_CHROME -DgridHubURL=http://localhost:4444/wd/hub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Once the execution is completed, we can see the workflow overview as below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A_mzoSSBww1N7cBXI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A_mzoSSBww1N7cBXI.png" width="512" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we take a look at each of the jobs for our UI tests that are using docker containers to execute the tests, we can see the below log information.&lt;/p&gt;

&lt;p&gt;Docker starts the stand-alone firefox container on port 4444 as we see in the output of the docker ps command. Then, using the gridHubURL we have sent the test requests to the container on the same port. Hence the tests are executed successfully on Firefox containers and the result is passed.&lt;/p&gt;

&lt;p&gt;Similarly, the Chrome container is started on port 4444, tests are executed and the execution is passed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AVS9Wp-QxwbtWKhs-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AVS9Wp-QxwbtWKhs-.png" width="512" height="235"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Semaphore CI Pipeline With docker-compose
&lt;/h2&gt;

&lt;p&gt;We have seen multiple examples of building test automation pipelines till now. We would be able to use Docker for spinning up the containers and executing our tests in them. Let us take this forward and explore building the automation pipelines with docker-compose in Semaphore CI.&lt;/p&gt;

&lt;p&gt;Docker-compose is a utility provided by Docker for defining and running the multi-container docker applications. We have specified all the instructions required to start the services in a declarative YAML file and trigger it with a simple docker compose up command.&lt;/p&gt;

&lt;p&gt;Let’s modify our configuration to run the same pipeline in browser containers launched by the docker-compose. First, we need to add the below code in the semaphore.yml file and run the workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Semaphore.yml file for complex flow — Docker-Compose&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# To execute this docker-compose yml file use `docker-compose -f docker-compose-v3.yml up`
# Add the `-d` flag at the end for detached execution
# To stop the execution, hit Ctrl+C, and then `docker-compose -f docker-compose-v3.yml down`
version: "3"
services:
  chrome:
    image: selenium/node-chrome:4.0.0-rc-1-prerelease-20210618
    volumes:
      - /dev/shm:/dev/shm
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
    ports:
      - "6900:5900"

  edge:
    image: selenium/node-edge:4.0.0-rc-1-prerelease-20210618
    volumes:
      - /dev/shm:/dev/shm
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
    ports:
      - "6901:5900"

  firefox:
    image: selenium/node-firefox:4.0.0-rc-1-prerelease-20210618
    volumes:
      - /dev/shm:/dev/shm
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
    ports:
      - "6902:5900"

  selenium-hub:
    image: selenium/hub:4.0.0-rc-1-prerelease-20210618
    container_name: selenium-hub
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Once the execution is completed, we could see the below details on the workflow overview page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AFFZILfIbZOfIJ_xh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AFFZILfIbZOfIJ_xh.png" width="512" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have noticed the semaphore.yml configuration file, there is a change in the way we set up the browser containers. We are using the below commands with docker compose and starting the required services.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl https://gist.GitHubusercontent.com/rakesh-vardan/c1dcf6531b826fad91f18c285d566a71/raw/ad90a18fe5e70f2d6aea06621b76d6e0329a4aab/docker-compose-sel.yml &amp;gt; docker-compose.yaml
$ docker-compose up -d
$ docker-compose ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;We have added the services in the docker-compose.yml file and downloaded the content for our execution. Once it is available in the build path, we have invoked the docker-compose up command to start the services using docker.&lt;/p&gt;

&lt;p&gt;From the log, we could observe that there are 4 containers created for Chrome, Edge, and Firefox browsers and Selenium hub. Since the hub is running on port 4444, we have redirected our test requests to the same hub URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2APu3WxO_O8oyHWP2o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2APu3WxO_O8oyHWP2o.png" width="512" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As per the below screen, the tests have been executed successfully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A7J2A4kVPYwr8pn_O.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A7J2A4kVPYwr8pn_O.png" width="512" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is one difference in the configuration in this example. If you have observed, we have added the docker-compose commands in the prologue section of the task only, and instead of creating a separate block for each UI test, we have added multiple jobs in the same block itself. This is because all jobs in Semaphore run in an isolated environment in virtual machines. So the services that start in one job are not automatically available to other jobs in the workflow. So to share the services across, we have added the commands in the prologue section.&lt;/p&gt;
&lt;h2&gt;
  
  
  Building Semaphore CI Pipeline With LambdaTest
&lt;/h2&gt;

&lt;p&gt;We are good with our previous examples and can execute the tests in Semaphore pipelines. However, suppose we have requirements for viewing the execution live, checking the execution logs, parallel execution, and recording execution sessions. In that case, this functionality is not readily available for us to include in our example. So, either we need to change the code or set up additional tools to enable this feature for our pipelines. So do we have a solution here? Yes, we can use a &lt;a href="https://www.lambdatest.com/selenium-automation?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;cloud Selenium Grid&lt;/a&gt; like LambdaTest.&lt;/p&gt;

&lt;p&gt;LambdaTest is a &lt;a href="https://www.lambdatest.com/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;cross browser testing&lt;/a&gt; cloud platform to perform automation testing on 2000+ combinations of real browsers and operating systems. It is very easy to configure a project using LambdaTest and start leveraging the benefits out of it. So, let’s integrate our pipeline with the LambdaTest cloud grid solution and see how it’s working.&lt;/p&gt;

&lt;p&gt;To start using the LambdaTest cloud, navigate to the LambdaTest Registration Page and sign-up for a new account (which is free to start with!). Once the LambdaTest account is activated, go to the &lt;a href="https://accounts.lambdatest.com/login?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;LambdaTest Profile&lt;/a&gt; Section and note the username and access key. We would need this LambdaTest username and accesskey to execute our tests on the LambdaTest platform.&lt;/p&gt;

&lt;p&gt;Let’s modify our configuration to run the same pipeline in browsers launched by the LambdaTest cloud grid. Add the below code in the semaphore.yml file and run the workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Semaphore.yml file for complex flow — LambdaTest&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: v1.0
name: Complex Pipeline with multiple browsers - parallel with LambdaTest
agent:
  machine:
    type: e1-standard-2
    os_image: ubuntu1804
blocks:
  - name: Build
    dependencies: []
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      jobs:
        - name: Build
          commands:
            - checkout
            - mvn -q package -DskipTests=true
            - cache store
  - name: API Smoke tests
    dependencies:
      - Build
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      prologue:
        commands:
          - checkout
          - cache restore
      jobs:
        - name: Run Smoke API tests
          commands:
            - mvn clean install -DsuiteXmlFile=testng-api.xml
      epilogue:
        always:
          commands:
            - test-results publish target/surefire-reports/junitreports/*.xml
  - name: Firefox tests
    dependencies:
      - API Smoke tests
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      prologue:
        commands:
          - checkout
          - cache restore
      jobs:
        - name: Run tests in Firefox
          commands:
            - mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=GRID_LAMBDATEST_FIREFOX
      epilogue:
        always:
          commands:
            - test-results publish target/surefire-reports/junitreports/*.xml
      secrets:
        - name: LT
  - name: Chrome tests
    dependencies:
      - API Smoke tests
    task:
      env_vars:
        - name: MAVEN_OPTS
          value: '-Dmaven.repo.local=.m2'
      prologue:
        commands:
          - checkout
          - cache restore
      jobs:
        - name: Run tests in Chrome
          commands:
            - mvn clean install -DsuiteXmlFile=testng.xml -Dbrowser=GRID_LAMBDATEST_CHROME
      epilogue:
        always:
          commands:
            - test-results publish target/surefire-reports/junitreports/*.xml
      secrets:
        - name: LT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Before triggering the build, we need to make sure that the below environment variables are set as secrets in the project settings in Semaphore CI. Secrets in Semaphore Continuous Integration are the objects that have global scope within an organization. These secrets can be accessed by the jobs or pipelines to which they have been connected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ARyYqfdLUzxTQESMS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ARyYqfdLUzxTQESMS.png" width="512" height="254"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LT_USERNAME - Username from the LambdaTest profile page.
LT_ACCESS_KEY - Access key obtained from the LambdaTest profile page.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The grid hub URL is formed based on the values that we set in the environment variables, as shown below:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://&amp;lt;username&amp;gt;:&amp;lt;accessKey&amp;gt;@hub.lambdatest.com/wd/hub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Where username is the Username, accessKey is the access key from the LambdaTest account.&lt;/p&gt;

&lt;p&gt;Once the execution is completed, we could see the below details on the workflow overview page in the Semaphore CI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A3eL1BWwBFV0j1MQ5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A3eL1BWwBFV0j1MQ5.png" width="512" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And from the detailed logs, we could see that the execution is successful in Firefox and Chrome browsers. Furthermore, we can also see the command used to execute the tests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AF2l0ntYPqA4qBVzF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AF2l0ntYPqA4qBVzF.png" width="512" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AVcxZQ0-zSrzSBC1Z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AVcxZQ0-zSrzSBC1Z.png" width="512" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This looks good, but how about the execution statistics and information. Once the Semaphore CI completes the test execution, we can navigate to the &lt;a href="https://accounts.lambdatest.com/register?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=nov23_pk&amp;amp;utm_term=pk&amp;amp;utm_content=blog" rel="noopener noreferrer"&gt;LambdaTest Automation Logs&lt;/a&gt; to see our test execution in the Timeline view. To navigate to the Automation logs view, click on the test case to see other details such as execution recording, logs, etc.&lt;/p&gt;

&lt;p&gt;As we observe, we can see that 2 out of 5 parallel sessions are running in LambdaTest — one is on Chrome browser, and another is on Firefox browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ALIVb8UZC2EqXPto9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ALIVb8UZC2EqXPto9.png" width="512" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We could observe that 6 tests are executed in browsers available on the LambdaTest cloud grid from the timeline view.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Aa9EY_Vz93DwlY9aQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Aa9EY_Vz93DwlY9aQ.png" width="512" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the detailed view of automation logs, along with a recording of the test execution. Of course, we could also build very useful analytics like coverage, pass-failed ratio, and minutes consumed, etc., from the test execution results and build ready-to-use metrics.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ARwG6m3RVyHKY5aj2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ARwG6m3RVyHKY5aj2.png" width="512" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Isn’t it interesting? Without any code changes on our part, we can easily integrate our automation suite with LambdaTest’s cloud grid solution and benefit from the features that it provides to us.&lt;/p&gt;
&lt;h2&gt;
  
  
  Semaphore CI Additional Capabilities
&lt;/h2&gt;

&lt;p&gt;Let’s throw some light into some of the additional capabilities provided by the Semaphore CI. First, we will discuss the command-line options and the REST API provided by the Semaphore Continuous Integration tool.&lt;/p&gt;
&lt;h2&gt;
  
  
  Command Line Interface(CLI)
&lt;/h2&gt;

&lt;p&gt;Semaphore command line interface(CLI) is called sem. It enables us to create and manage the Semaphore projects and resources directly from the command line terminal. Sem is a very powerful CLI utility that comes with the power of managing all the resources of Semaphore — workflows, pipelines, jobs, blocks, organizations, etc.&lt;/p&gt;

&lt;p&gt;To get started using the sem cli, open a terminal either in a Linux machine or a macOS machine. Currently, the sem cli is not available to Windows OS. Issue the below command to download and run the script to have the cli available on your machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://storage.googleapis.com/sem-cli-releases/get.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Aom4P1miN6B5K7Frz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Aom4P1miN6B5K7Frz.png" width="512" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once done, use the sem connect command along with the organization token to connect to the organization.&lt;/p&gt;

&lt;p&gt;sem connect ORGANIZATION.semaphoreci.com ACCESS_TOKEN&lt;/p&gt;

&lt;p&gt;Get your access token from the below page in Semaphore CI. If there is no token available for your account, create one for yourself using the Generate API token button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A78FDuAYB_KxaRnRB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A78FDuAYB_KxaRnRB.png" width="512" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you are connected to the required organization, we can issue the sem commands to manage our resources in Semaphore CI. Check the available option using the sem –help command.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AcGqCKUDbOnAOVYdB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AcGqCKUDbOnAOVYdB.png" width="512" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let us see if we can get all the pipelines available in our project. So issue the sem command as below along with the project name. So we could see all the pipelines that we have used till now along with their details.&lt;/p&gt;

&lt;p&gt;sem get pipelines -p semaphoreci-selenium-lambdatest&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AALF2mmaPFRleg0iX.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AALF2mmaPFRleg0iX.png" width="512" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ATRdByNzYsscoMsJB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ATRdByNzYsscoMsJB.png" width="512" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we see below, we can check all the logs generated as part of the specific job.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2800%2F0%2AAjhlIixN1VpDazRo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2800%2F0%2AAjhlIixN1VpDazRo.png" width="800" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most of the actions we perform on the Semaphore web interface can be performed using the command line option sem. Please refer to the official Semaphore CLI documentation to get other available options in sem CLI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Thank you for reading our detailed article on building test automation pipelines using Semaphore CI. We discussed different approaches for creating the workflows in Semaphore, starting with a simple one. Then we discussed the complex pipelines of both sequential and parallel execution. We have also discussed leveraging docker in our pipelines, including the docker-compose utility. Finally, we discussed integrating the workflows with the cloud grid solution — LambdaTest. As part of our examples, we have covered some of the essential concepts from Semaphore CI like workflows, blocks, jobs, pipelines, and secrets, etc. We also touched upon using the Semaphore Continuous Integration using the CLI and REST API. We hope this article can help you get started with building pipelines with Semaphore CI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Testing!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
