Developing a Testable Application: Why We Chose Electron
In 2013, we on the Tryon Solutions development team were tasked with improving our deployment processes to provide leaner, more valuable deliverables to our customers. When reflecting on how to improve, we realized that our lack of automated testing was causing us considerable headaches: The extra time required to stop, correct, and resume our work was robbing us of forward motion.
Thus, Cycle was born! Originally built as an internal tool focused on Behavior-Driven Strategies, the original architecture was borrowed from another internal tool we were using at the time. However, as Cycle adoption grew and customer feedback flowed in, we began to realize the original architecture was somewhat monolithic, stagnant and was difficult to test.
Cycle’s original architecture required too much boilerplate code, even when updating small aspects of the UI — which was to tightly coupled with the execution logic on the backend. We felt limited in our ability to provide a user-friendly, modern experience. We wanted Cycle to feel like an approachable and welcoming application, using familiar interactions with a guided experience while also streamlining our development processes and ensuring as much of the application as possible could be automatically tested.
When we embarked on the journey to rebuild Cycle from the ground up, there were many issues to consider, but our prime concern was what technology stack we’d use to run our application’s front end. Version 1 of Cycle was built with Java Swing, but we found that framework lacking in terms of flexibility and had difficulty adapting it to newer application design patterns. The fact that several members of the development team had experience building web applications led us to focus on platforms that use standard web languages. After evaluating several options, Electron emerged as the clear winner.
The following are the four primary reasons why we chose Electron for developing a testable application:
Supports web technologies
Electron is basically a self-contained Chromium browser sitting on top of Node.js. This duo creates a powerful and easy way to utilize the vast amount of excellent web technologies available. Chromium accounts for over half of all web browser usage and allowed us to seamlessly integrate libraries like Webix, Codemirror, and Xterm.js into our application. Styling these elements was a breeze for our designer with the use of SASS.
The use of Chromium means we can test Cycle with Cycle’s very own web steps. By setting the Custom Chrome Location setting in the Preferences to our compiled version of the Cycle Electron application, we can run web steps with the Chrome web driver, allowing far more robust and precise testing of the application compared to only using Cycle’s desktop steps.
The Node.js side of Electron gave us easy cross-platform access to file menus and dialogs as well as the entire NPM.js ecosystem. With NPM, we were able to use a number of excellent packages – Gulp.js is a team favorite – to help us maintain efficient development and build processes. Tools like Gulp.js excels our test driven development of Cycle as rebuilding a packaged version of Cycle to test with our web steps is only a quick command away.
Powerful debugging dev tools
At the heart of Chromium lies Chrome DevTools, a vast toolset with deep access to all facets of the application. The most important of these tools is the Elements tab. This tool allows for quick investigation and editing of any element within the DOM as well as any associated CSS styles. The value of the Elements tab can hardly be overstated when creating tests with Cycle’s web steps. This tab takes all the guesswork out of writing pinpoint tests by allowing us to simply select an element in the DOM, making the creation xpaths or finding IDs a breeze.
Other extremely helpful tools in the DevTools include: the debugger in the Sources tab is an invaluable tool when troubleshooting errors, allowing the user to start and stop a process and analyze any data contained within; the robust Performance tab highlights glaring pitfalls when trying to improve application speed and response via an interactive timeline; and the Rendering tab to easily view frames per second during intense workloads and to highlight areas that get repainted too often.
Decoupling of front-end and back-end
The client-server architecture that Cycle 2.0 is built upon separates the engine of the application from the user interface. Well-designed software inherently separates these parts into views and controllers, this boundary can be even further defined through total decoupling. While our backend focuses on complex data management utilizing languages and tools like Scala and Akka, our Electron-powered client is essentially self-contained web browser listening to data from this backed via websocket. Having these as two completely separate entities means we test these parts individually or together in a full system test.
Though Cycle currently only supports Microsoft Windows, Electron’s cross-platform compatibility opened the door to other operating systems. We can design the application once without having to worry about differences between Windows, OSX, and Linux. The fact that most of the development team works on Apple computers but builds for Windows-based users is testament to the easy cross-compatibility. Very little code needs to take into account the user’s operating system before executing, with one immediate exception being the menu bar. Even so, accommodating this change is easy, requiring only a few extra items when on OSX. Other than that, Electron handles any differences behind the scenes. This cross-platform compatibility means running our large suite of Cyclescript Feature files as part of a continuous integration test server requires little extra thought when creating the test, as the web steps work the same on any machine.
In summary, we’re very happy with our choice to use Electron. Being able to test Cycle with Cycle not only catches bugs or missed requirements earlier in our development lifecycle but also allows us, as developers, constant real-world use of our own application and a platform for better communication and collaboration with our product owner.
This post was written by:
Cameren is part of the Cycle software development team. He enjoys building out the user interface and helping to create a good user experience.