Earlier this year, I used Selenium in my company to write client-side tests. This is great for developers who write primarily in Scala. The problem is that learning Scala and Selenium are high standards for developers writing end-to-end tests. We have a lot of developers who almost always write in TypeScript. As a newcomer to Scala, client-side testing of new functionality is so difficult that tests are often not written. When I discovered Puppeteer, it seemed to be the right tool for this problem. Developers can write tests in TypeScript, a language they are more familiar with. We’ve already written unit tests using Jasmine, so the ability to create Puppeteer tests using Jasmine is a clear win. Devs can also connect to Chrome DevTools while running tests so they can use the debugger they are familiar with. All of these features seem ideal for making client-side tests easier to write. Puppeteer also has some advantages over Selenium.

Simpler JavaScript execution

A powerful feature of Selenium and Puppeteer is the ability to run JavaScript in a browser. The use of this feature is almost endless, and using it in Puppeteer is an almost effortless comparison of the following two pieces of code: Scala + Selenium

val evalResult = Json. Parse (driver. ExecuteAsyncScript (var callback = "" "the arguments [the arguments. The length - 1]; asyncFunction().then(callback); "" "). AsInstanceOf [String])Copy the code

TypeScript + Puppeteer

const evalResult = await page.evaluate(() => asyncFunction());
Copy the code

TypeScript versions can be simpler and have some additional advantages. First, the TypeScript version handles exceptions automatically. If AslenFunction fails in the Selenium version, no errors occur; Instead, it will time out. You can, and probably should, create a wrapper function to simplify calling JavaScript and handle errors correctly if you use Selenium. However, since the underlying implementation is simpler, Puppeteer is the better choice here. You do not need to modify the interface. The Puppeteer version also has the advantage of TypeScript type-checking. You can declare evaluate internally used functions and variables. If you have syntax or type errors, TypeScript catches them. In Selenium, you do not catch errors until you try to run tests. The core of these advantages boils down to having the test driver use the same language as the browser. This makes connecting the two more seamless. As a comment, you can write Selenium tests in TypeScript and implement a similar seamless evaluate implementation, but this is not an option for our Scala code – which is why I listed this as the reason I want to switch to Puppeteer.

Network to intercept

This is Puppeteer’s greatest advantage over Selenium. Your test code can log, modify, block, or generate responses to requests made by the browser. At first glance, this may not seem like a very useful feature, but it helps solve many difficult problems.

The test handles failed requests

By letting Puppeteer selectively fail certain requests, you can verify that your product fails properly in these cases. You can use this procedure to verify that the error message is correct if the upload fails. If the image is not loaded, you can verify that the page layout crashes.

Simulated third-party services

I have first-hand experience using network interception in this category. We want to write some automated tests for Salesforce blocks. What’s the problem? Our Salesforce plug-in relies on calling the Salesforce API. If we write tests to log into our existing Salesforce account to run these tests, we run into some problems: We had to rely on the test machine that was reliably connected to Salesforce, and a change in Salesforce’s GUI would cause our test to suddenly fail without any errors, Salesforce could detect that we were logging in as a robot and installing CAPTCHA or requiring two-step verification. It’s amazing. Puppeteer has solved this problem for us. We can write a simulated Salesforce API that runs locally. Any request to Salesforce is intercepted by the Puppeteer and the forged data is returned in its place.

Testing offline mode

Puppeteer can also simulate being offline. You can write tests to ensure that your product handles the loss of Internet connection correctly. This ability was critical to writing unit tests for offline mode functionality that we recently added to the product. We were able to create unit tests to verify that the changes were saved offline, and that the changes were saved to the server when the connection returned. Without this feature, we would rely entirely on unit testing or try to fake offline modes in ways that least tested our offline capabilities.

debugging

Because Puppeteer can receive notifications of all requests and responses from the browser, you can also simply log this information – useful when trying to diagnose failed tests running on the build server. As part of our build system, when one of our Puppeteer tests failed, we got a screen shot of all the tabs that were open at the time of the failure, as well as a complete console log dump and all the requests made by the browser. This information helps diagnose test failures from build reports without having to run them locally. It is also very valuable when the tests fail only on our build server, where you do not see the test run and only get the test results.

Single browser, single language

That sounds like a disadvantage. If I were writing an article on why Selenium is better than Puppeteer, I would definitely write that Selenium gives you more options about what language you want to use, and more importantly, Selenium lets you run your tests in multiple browsers. So why do I give Puppeteer credit for lacking these features? These features cost money. When searching for code examples on Selenium, you will often find examples in another language. You can search online and find a good tutorial on how to use Selenium or a good code snippet that shows what you want to accomplish, but they may be in a language you don’t use and aren’t familiar with. Moreover, Selenium’s promise of “write once, run in any browser” doesn’t always hold true in the real world. For some reason, some tests will be passed in one browser for no clear reason in the other. Bugs in different browser drivers can prevent tests from running reliably on all browsers. If you’re willing to put in the extra work, you can run tests on multiple browsers, but only for a single browser, which can greatly simplify your development load.

So should you choose Selenium over Puppeteer?

In my case, I think it is right to choose Puppeteer instead of Selenium. I am not saying that everyone should abandon Selenium. We still write and maintain Selenium tests for those who like them. Nor do I recommend that everyone choose Puppeteer over Selenium. I chose Puppeteer because it offers simpler Javascript execution, web interception, and a simpler, more centralized library. I hope these points are useful so that you can make an informed choice if you want to do client-side testing.

After watching

Click like, so that more people can see this content (collection does not click like, are playing rogue -_-) pay attention to the public number “new front-end community”, enjoy the first article experience! Focus on conquering one front-end technical difficulty every week.