<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Vishesh Srivastava on KDE Blogs</title><link>https://blogs.kde.org/authors/thatdevishesh/</link><description>Recent content in Vishesh Srivastava on KDE Blogs</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Tue, 24 Mar 2026 20:32:00 +0000</lastBuildDate><atom:link href="https://blogs.kde.org/authors/thatdevishesh/index.xml" rel="self" type="application/rss+xml"/><item><title>[SoK 2026] Appium Testing for Lokalize</title><link>https://blogs.kde.org/2026/03/20/sok-appium-testing-lokalize/</link><pubDate>Fri, 20 Mar 2026 00:00:00 +0000</pubDate><author>Vishesh Srivastava</author><guid>https://blogs.kde.org/2026/03/20/sok-appium-testing-lokalize/</guid><description>&lt;p&gt;Hey there! I'm Vishesh Srivastava, and this is the full write-up for my SoK 2026 project: adding Appium-based UI tests to &lt;a href="https://apps.kde.org/lokalize/"&gt;Lokalize&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="so-whats-lokalize"&gt;So what's Lokalize?&lt;/h2&gt;
&lt;p&gt;It's KDE's translation tool - the app translators use to work with PO files and manage translation projects. It already had unit tests, but no UI tests. So the goal of this project was to setup a UI testing framework using Appium.&lt;/p&gt;
&lt;h2 id="the-first-task-bug-514468"&gt;The first task: Bug 514468&lt;/h2&gt;
&lt;p&gt;Before Appium work started, my first task was &lt;a href="https://bugs.kde.org/show_bug.cgi?id=514468"&gt;Bug 514468&lt;/a&gt;. The issue was that copyright year strings in PO headers could become very long, like:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;2006, 2010, 2011, 2012, 2013, 2014, 2015, 2017, 2018, 2019, 2020, 2021&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;instead of the shorter:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;2006, 2010-2015, 2017-2021&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I was asked to write a failing test first, so I added a placeholder &lt;code&gt;simplifyYearString&lt;/code&gt; function and wrote a unit test for the expected collapsed output. At first it was pushed with &lt;code&gt;QEXPECT_FAIL&lt;/code&gt;, since the actual implementation was meant to be done separately.&lt;/p&gt;
&lt;p&gt;This was small compared to the main project, but it helped me get comfortable with setting up KDE's build system and how tests are added to Lokalize.&lt;/p&gt;
&lt;h2 id="building-the-appium-setup-from-scratch"&gt;Building the Appium setup from scratch&lt;/h2&gt;
&lt;p&gt;Lokalize had no Appium setup at all, so this part started from zero.&lt;/p&gt;
&lt;p&gt;The first tests were simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;simple_open.py&lt;/code&gt; just opens Lokalize and closes it&lt;/li&gt;
&lt;li&gt;&lt;code&gt;file_open.py&lt;/code&gt; opens the File menu and checks that the open dialog path works&lt;/li&gt;
&lt;li&gt;&lt;code&gt;workflowtest.py&lt;/code&gt; simulates an actual translator workflow&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That last one was the main test I was aiming for. It opens a &lt;code&gt;.po&lt;/code&gt; file with untranslated entries, types translations into the editor, uses &amp;quot;Approve and Go Next&amp;quot;, checks that the UI updates properly, verifies the status bar reaches &lt;code&gt;Not ready: 0&lt;/code&gt;, and finally saves the file.&lt;/p&gt;
&lt;p&gt;That made it a proper end-to-end test.&lt;/p&gt;
&lt;h2 id="problem-encountered-in-the-last-test"&gt;Problem encountered in the last test&lt;/h2&gt;
&lt;p&gt;Appium depends on accessibility information to find and interact with widgets. Lokalize's editor fields did not expose accessibility ids for Appium to call them (found using &lt;a href="https://apps.kde.org/accessibilityinspector/"&gt;accessibilityinspector&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;So I had to make changes in &lt;code&gt;editorview.cpp&lt;/code&gt; to add object names and accessible names to the widgets. Without that, the test scripts could open the app and click menus, but they were basically blind when it came to the translation editor.&lt;/p&gt;
&lt;p&gt;Other KDE apps with Appium tests, like Dolphin and KCalc, had tests which used these and were useful references here.&lt;/p&gt;
&lt;p&gt;Below is a demo of this working:&lt;/p&gt;
&lt;video controls preload="metadata" width="800"&gt;
 &lt;source src="Demo_appium.mp4" type="video/mp4"&gt;
&lt;/video&gt;
&lt;h2 id="making-it-run-with-the-rest-of-the-test-suite"&gt;Making it run with the rest of the test suite&lt;/h2&gt;
&lt;p&gt;The next step was integrating the Appium tests into CMake so they could run as part of Lokalize's normal test flow.&lt;/p&gt;
&lt;p&gt;I added an &lt;code&gt;appiumtests/CMakeLists.txt&lt;/code&gt; and a &lt;code&gt;BUILD_APPIUM_TESTS&lt;/code&gt; option, so the tests can be enabled and run through the normal KDE tooling:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kde-builder --run-tests lokalize --no-include-dependencies --no-src --cmake-options&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-DBUILD_APPIUM_TESTS=ON&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That was important because UI tests are much less useful if they live outside the project's regular test workflow. The &lt;code&gt;BUILD_APPIUM_TESTS&lt;/code&gt; option was kept because it was not advised to run Appium tests in the CI/CD.&lt;/p&gt;
&lt;h3 id="another-issue-making-the-tests-independent-of-the-local-user-setup"&gt;Another issue: Making the tests independent of the local user setup&lt;/h3&gt;
&lt;p&gt;One issue was that on opening, Lokalize asked for a name and email address which I was earlier typing manually. This was undesired since tests had to be run without user intervention.&lt;/p&gt;
&lt;p&gt;So I added a file &lt;code&gt;test_support.py&lt;/code&gt;, that creates a temporary config directory, writes a minimal &lt;code&gt;lokalizerc&lt;/code&gt;, and launches Lokalize with that isolated configuration. That way the tests do not depend on my own existing settings or require any user input.&lt;/p&gt;
&lt;p&gt;I also reused that helper across the test files so they stopped repeating the same Appium setup code again and again.&lt;/p&gt;
&lt;h3 id="writing-a-failing-bug-test"&gt;Writing a failing bug test&lt;/h3&gt;
&lt;p&gt;After the main workflow test, I also added another Appium test for a real UI bug: after closing a project, translational tab menus should become disabled.&lt;/p&gt;
&lt;p&gt;This test is in &lt;code&gt;project_close.py&lt;/code&gt;. It opens a project, closes it, and then checks that menus like &lt;code&gt;Edit&lt;/code&gt;, &lt;code&gt;Go&lt;/code&gt;, and &lt;code&gt;Sync&lt;/code&gt; are disabled.&lt;/p&gt;
&lt;h3 id="fixing-how-the-tests-are-executed"&gt;Fixing how the tests are executed&lt;/h3&gt;
&lt;p&gt;At first, the Appium tests were being discovered and registered individually in CMake. The next task was to run them from a single &lt;code&gt;run_all.py&lt;/code&gt; runner. Now all the tests use a single KWin instance like they do in other projects like Dolphin.&lt;/p&gt;
&lt;p&gt;This also makes writing new tests simpler since adding a test just means adding a new line in the run_all.py. So instead of CMake looping over every Python file, it now calls the runner once.&lt;/p&gt;
&lt;p&gt;There was also one annoying issue here: &lt;code&gt;--run-tests&lt;/code&gt; was reporting success even when one of the Appium tests had failed when run manually. Because of that, I had to return &lt;code&gt;sys.exit(1)&lt;/code&gt; explicitly from the runner when the test result was not successful. Without that, the tests looked successful even after failing.&lt;/p&gt;
&lt;p&gt;Below is a demo of this working:&lt;/p&gt;
&lt;video controls preload="metadata" width="800"&gt;
 &lt;source src="Demo_appium_tests.mp4" type="video/mp4"&gt;
&lt;/video&gt;
&lt;h2 id="outcomes-achieved"&gt;Outcomes achieved&lt;/h2&gt;
&lt;p&gt;By the end of the project, Lokalize had:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a working Appium test setup&lt;/li&gt;
&lt;li&gt;basic tests for startup and opening files&lt;/li&gt;
&lt;li&gt;a full workflow test covering translation editing and saving&lt;/li&gt;
&lt;li&gt;helper files to make tests cleaner and independent of local user config&lt;/li&gt;
&lt;li&gt;integration into the normal test system through CMake&lt;/li&gt;
&lt;li&gt;a single test runner file&lt;/li&gt;
&lt;li&gt;documentation on how to run/write tests.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="final-thoughts"&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;This was a really enjoyable project. I got to work on Appium testing, the KDE build system, and a bit of bug hunting.&lt;/p&gt;
&lt;p&gt;Many thanks to &lt;a href="https://invent.kde.org/finw"&gt;Finley Watson&lt;/a&gt; for his guidance throughout the project and for helping whenever I got stuck.&lt;/p&gt;
&lt;p&gt;The best part for me is that the work is extendible. New Appium tests can be added without rebuilding the whole setup from scratch, which was the main point of the project in the first place.&lt;/p&gt;</description></item><item><title>[SoK 2026] Halfway update: Appium Testing in Lokalize</title><link>https://blogs.kde.org/2026/03/08/sok-appium-testing-lokalize-halfway/</link><pubDate>Sun, 08 Mar 2026 00:00:00 +0000</pubDate><author>Vishesh Srivastava</author><guid>https://blogs.kde.org/2026/03/08/sok-appium-testing-lokalize-halfway/</guid><description>&lt;p&gt;Hey there! I'm Vishesh Srivastava, and we're at the halfway mark of my SoK 2026 project — writing Appium-based UI tests for &lt;a href="https://apps.kde.org/lokalize/"&gt;Lokalize&lt;/a&gt;. I was a bit late for the halfway mark, but we're still on track.&lt;/p&gt;
&lt;h2 id="so-whats-lokalize"&gt;So what's Lokalize?&lt;/h2&gt;
&lt;p&gt;It's KDE's translation tool — the app that translators use to work with PO files and manage translation. It does its job well but it had zero UI tests. None. My job this SoK is to fix that.&lt;/p&gt;
&lt;h2 id="the-starting-days-january"&gt;The starting days (January)&lt;/h2&gt;
&lt;p&gt;My first task was &lt;a href="https://bugs.kde.org/show_bug.cgi?id=514468"&gt;Bug 514468&lt;/a&gt; — where copyright year strings in PO headers would be very long like &lt;code&gt;2006, 2010, 2011, 2012, 2013, 2014, 2015, 2017, 2018, 2019, 2020, 2021&lt;/code&gt; instead of the more concise &lt;code&gt;2006, 2010-2015, 2017-2021&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I was asked to write a failing test first. So I added a &lt;code&gt;simplifyYearString&lt;/code&gt; placeholder function, wrote a unit test that expects the collapsed range output, and marked it with &lt;code&gt;QEXPECT_FAIL&lt;/code&gt; since the actual implementation was going to be done by someone else. It was updated to expect to pass when the bug was fixed.&lt;/p&gt;
&lt;p&gt;More importantly, this got me comfortable with KDE's setup, kde-builder, and how the testing framework works.&lt;/p&gt;
&lt;h2 id="the-main-work-appium-tests-february--march"&gt;The main work: Appium tests (February – March)&lt;/h2&gt;
&lt;p&gt;This is where the real fun began. Lokalize had absolutely no Appium setup, so everything was built from the ground up.&lt;/p&gt;
&lt;h3 id="first-steps"&gt;First steps&lt;/h3&gt;
&lt;p&gt;My first tests were very simple. &lt;code&gt;simple_open.py&lt;/code&gt; literally just opens Lokalize and closes it. That's the whole test. &lt;code&gt;file_open.py&lt;/code&gt; was the next step: open the app, click File, click Open, and confirm the dialog shows up. Not much but you have to crawl before you can walk.&lt;/p&gt;
&lt;h3 id="a-bug-i-encountered"&gt;A bug I encountered&lt;/h3&gt;
&lt;p&gt;Here's something I found: Appium finds UI elements through accessibility properties, and Lokalize's editor text fields didn't have any (found using &lt;a href="https://apps.kde.org/accessibilityinspector/"&gt;accessibilityinspector&lt;/a&gt;). So my test scripts were essentially blind — they could see menus and buttons but couldn't interact with the actual editor. I had to edit &lt;code&gt;editorview.cpp&lt;/code&gt; to add object names and accessible names to the widgets to actually get Appium to see them.&lt;/p&gt;
&lt;p&gt;Other KDE apps with Appium tests (Dolphin, KCalc) already had these, but nobody had needed them in Lokalize before. These were my reference for writing the code.&lt;/p&gt;
&lt;h3 id="the-workflow-test-the-one-im-actually-proud-of"&gt;The workflow test (the one I'm actually proud of)&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;workflowtest.py&lt;/code&gt; is the test that simulates what a translator would actually do:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open a &lt;code&gt;.po&lt;/code&gt; file with two untranslated entries&lt;/li&gt;
&lt;li&gt;Type a translation into the target field&lt;/li&gt;
&lt;li&gt;Hit &amp;quot;Approve and Go Next&amp;quot;&lt;/li&gt;
&lt;li&gt;Do the same for the second entry&lt;/li&gt;
&lt;li&gt;Check if the editor tab UI was updated successfully&lt;/li&gt;
&lt;li&gt;Check that the status bar says &lt;code&gt;Not ready: 0&lt;/code&gt; — meaning everything's translated&lt;/li&gt;
&lt;li&gt;Save the file&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Below is a demo of this working:&lt;/p&gt;
&lt;video controls preload="metadata" width="800"&gt;
 &lt;source src="Demo_appium.mp4" type="video/mp4"&gt;
&lt;/video&gt;
&lt;p&gt;It's a proper end-to-end test.&lt;/p&gt;
&lt;h3 id="integrating-with-cmake"&gt;Integrating with CMake&lt;/h3&gt;
&lt;p&gt;To make it so that these tests run along with all other tests with &lt;code&gt;kde-builder --run-tests&lt;/code&gt;, I added a &lt;code&gt;CMakeLists.txt&lt;/code&gt; for the appiumtests directory and added it into the project's build system behind a &lt;code&gt;BUILD_APPIUM_TESTS&lt;/code&gt; option:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kde-builder --run-tests lokalize --no-include-dependencies --no-src --cmake-options&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-DBUILD_APPIUM_TESTS=ON&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now the tests integrate with the Appium tests just like they do in other KDE apps.&lt;/p&gt;
&lt;h2 id="next-steps"&gt;Next steps&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Writing failing tests for bugs&lt;/li&gt;
&lt;li&gt;Edge case tests&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="final-thoughts-for-now"&gt;Final thoughts (for now)&lt;/h2&gt;
&lt;p&gt;It's been a enjoyable experience and many thanks to &lt;a href="https://invent.kde.org/finw"&gt;Finley Watson&lt;/a&gt; for offering great help along the way.&lt;/p&gt;
&lt;p&gt;Halfway there. Let's see what happens next.&lt;/p&gt;</description></item></channel></rss>