The power of Chrome Devtools Protocol
Part I — Tracing Domain
First of all, I would like to describe what CDP means. “Chrome Devtools Protocol” is a powerful protocol to debug and profile Chrome. Through this protocol, you will have access to different “domains” that will allow you to interact with the browser as you would do for example using Chrome Developer Tools. Here is when Test Automation and Performance testing come and I want to start this article by describing how you can integrate CDP in your Test Automation or performance testing process independently of any automation tool, just using CDP without doing too much effort. Between the features that you can use, there are for example tracing, performance, emulating network conditions (network throttling), reading console messages, mocking geolocation, and much more.
I’ll describe in this article some test scenarios that happen in common life during the testing process, it will take advantage of this great protocol and you will access programmatically the gems that Chrome has.
The article is divided into different parts such as:
- Tracing domain that will allow you to fetch tracing metrics.
- Network domain where we will capture network requests and export them to HAR files.
- Runtime domain that will allow us to extract console logs, errors, and warnings from the browser.
- Performance domain that will allow you to fetch performance metrics.
Required packages
Some dependencies will be needed to work with CDP. I have added these to my package.json file to use them as utilities for the different features provided by each domain.
npm install chrome-remote-interface
npm install chrome-har
npm install devtools-protocol
npm install @types/har-format
Package References
- chrome-remote-interface → An abstraction over CDP. It can be found here.
- chrome-har → transform network events messages into HAR format. It can be found here.
- devtools-protocol → TypeScript definitions for the protocol’s types. It can be found here.
- @types/har-format → TypeScript definitions for the har format. It can be found here.
Disclaimer
As a result of this article and more as an investigation work, I have developed a wrapper on top of the mentioned packages that will show how to use this protocol. It can be found at https://github.com/germanbisogno/cdp-utils, and it is not a replacement for any actual tool or library; instead, it is just a wrapper with common utilities for Test Automation or Performance testing. If you wish to use the mentioned packages in your project, you can import these packages directly using chrome-remote-interface or chrome-har like this project is referencing in its package.json.
Please, check the following diagram for a better understanding:
Using Tracing domain
Chrome Developer Tools allow you to record performance and you can export this to a JSON file, as the image below shows, you can do it manually using developer tools:
For this example, we’ll be recording a simple test action that is searching in Google. Once you finish the recording it will show a lot of rich information about the tracing, for example:
As you can see there is information about loading, scripting, rendering, and painting and it has also captured screenshots of my manual test (search in Google).
If you need more information about how to use the performance tab, you can check here.
How do we automate?
It can be done using the Tracing domain which is currently an experimental feature in CDP and will capture what we have done previously using developer tools.
Notice there are great frameworks like Puppeteer, Testcafe, and Selenium 4, that are using this protocol already. You can take a look at those too and do your implementation.
We will be using CDP and I have selected Selenium as a test framework to show how to integrate it with this protocol. Now, let’s jump into the code!
First of all, we need to create a cdpClient.ts file for the CDP connection:
Now that we have a class to instantiate the CDP client, let’s create an abstract class traceOperations.ts to define in this case two functionalities to startTrace
and stopTrace
, then we will extend from this class to the rest of the specialized classes.
Notice when we stop the trace, it will be possible to retrieve data from the different domains such as Runtime, Tracing, and Performance which includes getting metrics when we start and stop the trace.
Let’s implement theTracing
class and extend it fromTraceOperations.
We have used some commands here, likeTracing.start
, it will start the trace and will receive a trace configuration, we will describe later what can be configured on it.
We make use of two eventsTracing.dataCollected
that will be used to collect the data from the events produced in our Chrome andTracing.tracingComplete
that is called when we execute Tracing.End
just after the data is collected, then we will be able to store the trace into a JSON file optionally that will be importable from Chrome or just return the events to the test and perform assertions or any other operation that your want to do with the data.
For more information about the trace event format, see this link.
Configuration file
Notice that the Tracing.start
command requires a configuration that is described here, in this example, we are providing the cdp.config.json part where it is specified which are the categories that we want to include in the trace. For example:
Notice using “-*” in line 5. You are excluding any category and in this example, we have explicitly specified them, for example, “disabled-by-default-devtools.screenshot” will be used to include screenshots in our trace.
Developing a test!
We have the class to make the client connection and another class to perform the tracing. So, let’s implement them in our Selenium test!. It will search in Google for given criteria.
It is worth mentioning that In the following example, we are using POM (Page Object Model, a pattern used in Test Automation) to create a Google page. You can find more detailed information about this pattern here.
A couple of important things to highlight in the previous code, note — remote-debugging-port=${port}. This will be required to start Chrome using CDP in a particular port, commonly 9222. In this case, we are using the endpoint-utils package to get a free port; you can find it here. If you are running tests in parallel, it will be good to use a tool to get a free port for each CDP Session.
Finally, we can import the tracing.json file in Chrome, and voila! we have again that rich information in our hands!
Hope that you have enjoyed the previous section and you can start using the Tracing domain right away!
Conclusion
We went into the Tracing domain and some of its different features, as you can see this is why I called this article “The power of CDP”. This is powerful, there are many operations that we can do with Chrome and many other domains that we can exploit which is a real gem for developers and testers or whoever is interested in this great protocol. There is a lot of rich information to capture when you are testing your application, creating baselines, and monitoring your test results.
We will continue covering more domains in the next articles. I also want to cover more about processing all this information and visualize it in a fashion way by introducing more processing and reporting tools.
Hope you have enjoyed this journey! See you next time!
Thanks for reading!