<?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: Joost van Wollingen</title>
    <description>The latest articles on DEV Community by Joost van Wollingen (@jpjwolli).</description>
    <link>https://dev.to/jpjwolli</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%2F174405%2F27f874d1-817b-41ba-a5f7-c515b14192a7.jpg</url>
      <title>DEV Community: Joost van Wollingen</title>
      <link>https://dev.to/jpjwolli</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jpjwolli"/>
    <language>en</language>
    <item>
      <title>Alert on Test Results Easily With Alerticorn 0.1</title>
      <dc:creator>Joost van Wollingen</dc:creator>
      <pubDate>Wed, 19 Feb 2025 21:35:05 +0000</pubDate>
      <link>https://dev.to/jpjwolli/alert-on-test-results-easily-with-alerticorn-01-4fci</link>
      <guid>https://dev.to/jpjwolli/alert-on-test-results-easily-with-alerticorn-01-4fci</guid>
      <description>&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%2Fmi1tki8lf5jzpbbw1f7q.jpeg" 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%2Fmi1tki8lf5jzpbbw1f7q.jpeg" alt="Alerticorn" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sometimes, you want to push test results to your team chat automatically.&lt;/p&gt;

&lt;p&gt;For example, in my current job, we associate sections of E2E tests with specific teams. When a test related to their functionality fails, they need to be notified so they can take a look.&lt;/p&gt;

&lt;p&gt;Sometimes I come across a test that fails under unknown circumstances, and I just can’t reproduce it right now. But I want to be alerted when it happens again, so I can investigate.&lt;/p&gt;

&lt;p&gt;With these usecases in mind (and mostly as a fun hobby project), I built &lt;a href="https://joostvanwollingen.github.io/alerticorn/" rel="noopener noreferrer"&gt;Alerticorn&lt;/a&gt; — a lightweight framework that makes sending notifications to team chats as easy as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Alerticorn Works
&lt;/h3&gt;

&lt;p&gt;Currently, Alerticorn extends JUnit 5, listening to results from test classes and test methods. If necessary, sends an alert to Slack, Teams or Discord.&lt;/p&gt;

&lt;p&gt;With the right configuration in place, sending a chat message is as simple as this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@ExtendWith(MessageExtension::class)
class MyTest {

  @Message(title = "The flux capacitator failed")
  @Test
  fun `flux capacitator test`() {
    // your test
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Messages can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Routed to different platforms and channels&lt;/li&gt;
&lt;li&gt;Customised with more information&lt;/li&gt;
&lt;li&gt;Generated with details from thrown exceptions&lt;/li&gt;
&lt;li&gt;Filtered based on the outcome of the test&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What’s Next? TestNG and Kotest Support
&lt;/h3&gt;

&lt;p&gt;Currently, Alerticorn supports JUnit 5, but I plan to add support for &lt;strong&gt;TestNG&lt;/strong&gt; and &lt;strong&gt;Kotest&lt;/strong&gt; , making it useful regardless of your test framework.&lt;/p&gt;

&lt;p&gt;Directly calling &lt;a href="https://joostvanwollingen.github.io/alerticorn/messaging/runwith/" rel="noopener noreferrer"&gt;RunWith.message&lt;/a&gt; is already supported, offering more flexibility for different use cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Philosophy Behind Alerticorn
&lt;/h3&gt;

&lt;p&gt;Alerticorn is built with a few core principles in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Convention over configuration&lt;/strong&gt;  — The defaults cover most use cases, but you can configure it fully if needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No unnecessary dependencies&lt;/strong&gt;  — It’s designed to be lightweight.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensibility&lt;/strong&gt;  — A plug-in system allows easy integration with other chat platforms or test runners.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning and fun&lt;/strong&gt;  — This project has been an excellent way to explore &lt;strong&gt;Kotlin, ServiceLoader, AI-assisted coding, Javadoc/KDoc, technical documentation (Docusaurus), Maven Central publishing, GitLab Actions,&lt;/strong&gt; and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Curious?
&lt;/h3&gt;

&lt;p&gt;Do you want to try it out? See a use case for it? Or maybe you think it’s a silly idea? Either way, I’d love to hear your thoughts in the comments.&lt;/p&gt;

&lt;p&gt;In the meantime, you can find the &lt;a href="https://joostvanwollingen.github.io/alerticorn/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; and &lt;a href="https://github.com/joostvanwollingen/alerticorn" rel="noopener noreferrer"&gt;source code&lt;/a&gt; on GitHub.&lt;/p&gt;




</description>
    </item>
    <item>
      <title>Building a Test Automation Library to Create and Manipulate Test Data</title>
      <dc:creator>Joost van Wollingen</dc:creator>
      <pubDate>Thu, 30 May 2024 20:42:57 +0000</pubDate>
      <link>https://dev.to/jpjwolli/building-a-test-automation-library-to-create-and-manipulate-test-data-521o</link>
      <guid>https://dev.to/jpjwolli/building-a-test-automation-library-to-create-and-manipulate-test-data-521o</guid>
      <description>&lt;p&gt;The past 4 years I’ve worked on a test automation library that is primarily used for end-to-end test automation, with some additional uses. In that time it has proven to be a very flexible, easily maintained and extensible piece of software. In this article I’ll share some of the underlying concepts and considerations we’ve used to build the library.&lt;/p&gt;

&lt;h3&gt;
  
  
  Goals — or “How Should This Thing Work?”
&lt;/h3&gt;

&lt;p&gt;Before setting up this library, there had been some earlier work done that was mostly pieced together JSON snippets, with text concatenation all over the place. Writing a new test meant copy/pasting tons of JSON every time. To top it off, it was written in an tool and language our developers had no knowledge of. Obviously, they wanted no part of it. It was not something I felt was fit to establish a strong foundation of test automation on top of.&lt;/p&gt;

&lt;p&gt;Goals we set for the library included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It should hide complexity when unnecessary&lt;/li&gt;
&lt;li&gt;It should give control when required&lt;/li&gt;
&lt;li&gt;It should be easy to use, and easy to contribute to&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What Are We Automating Again?
&lt;/h3&gt;

&lt;p&gt;The intended use for this library was twofold:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use it to automate tests against the public facing API of our platform&lt;/li&gt;
&lt;li&gt;Make it easy to reach certain states with the data it creates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our public API is a highly configurable one. Each consumer will call the same endpoints, but based on the configuration the required inputs can be very different. Endpoints must be called in a certain order and data most be provided consistently across these endpoints. For example: if you provide an address in call #1 it must be in the same country you provide in call #2.&lt;/p&gt;

&lt;p&gt;Completing the series of calls results in an entity being created, which has a complicated lifecycle, with different states, transitions and transition guards. The library should make it easy to create that initial entity, but also modify the state of the entity as desired.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hiding Complexity
&lt;/h3&gt;

&lt;p&gt;As described above, providing valid inputs to the API across multiple calls requires quite some specific domain and product knowledge. That’s fine if you care about testing the particulars of one set of configuration, but if you simply need an entity of type X to test something else elsewhere on the platform you might not be too enthusiastic about figuring out all those details.&lt;/p&gt;

&lt;p&gt;This is what I mean with hiding complexity, the library should provide its users an easy way to create complex data, without them having to know what data results in a valid entity, nor how to orchestrate the calls that are required.&lt;/p&gt;

&lt;p&gt;This is where we leverage Kotlin’s concrete interfaces, providing a blueprint for the process and for the pieces of data that must be provided.&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%2Fbn6v8uwok1naqrmv025n.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%2Fbn6v8uwok1naqrmv025n.png" alt="Product interface" width="729" height="796"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Product interface provides a default implementation for createShoppingCart, while the classes implementing provide specific, valid data through the interface methods.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Sensible Defaults
&lt;/h3&gt;

&lt;p&gt;Creating tests for a new product simply means implementing the methods that provide the data for a valid policy. All that remains to create that policy is calling a single line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;motor.createShoppingCart()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;a href="https://github.com/datafaker-net/datafaker" rel="noopener noreferrer"&gt;Datafaker&lt;/a&gt;, we provide localized and randomized data. Akin to James Bach’s &lt;a href="https://www.satisfice.com/blog/archives/5211" rel="noopener noreferrer"&gt;galumphing&lt;/a&gt;, this helped us to detect issues with inputs “that shouldn’t make a difference” more than once.&lt;/p&gt;

&lt;h3&gt;
  
  
  Need something specific?
&lt;/h3&gt;

&lt;p&gt;The setup with the Product interface is flexible enough to allow users to create very specific policies where needed, falling back to defaults for values that aren’t specified.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val verySpecificRiskAnswers = setOf(Answer("ALLRISK", "YES"))

motor.createShoppingCart(riskAnswers = verySpecificRiskAnswers)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Mind Your Consumer
&lt;/h3&gt;

&lt;p&gt;With this design for the test data library, we allow users to easily create randomized, valid test data with a one-line statement. No knowledge is required of the underlying API’s nor what data is required for a valid policy. At least…as long as they want to keep away from that complexity. The library is flexible enough to grant that control, and specify every input in detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage
&lt;/h3&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%2Fi2xxz8x6mxb7c20nzrhx.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%2Fi2xxz8x6mxb7c20nzrhx.png" alt="test data library" width="722" height="301"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Test Data Library powers different types of test and a service&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The test data library is used to power both E2E tests and system tests on integrated environments.&lt;/p&gt;

&lt;p&gt;Next to test engineers and developers, also business stakeholders often need test data to work with. You’ll probably be familiar with requests on Slack for data like X, Y or Z, and it might be cumbersome to create it manually every time.&lt;/p&gt;

&lt;p&gt;For this specific purpose we’ve build a web application with a thin UI layer that allows business stakeholders to easily create test data right from their browser. If they don’t have any specific requirements the sane defaults in the library make this a one click operation. If they have more specific demands, the UI allows for the same level of control as at the library level.&lt;/p&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;p&gt;The library has helped us to stay on top of an ever growing number of products, maintaining tests and rolling out changes with ease. A common change only has to be implemented in the Product interface, and all tests automatically follow the updated process.&lt;/p&gt;

&lt;p&gt;Adding a new product can be done in a matter of minutes and it’s very clear what information is needed to be able to start testing.&lt;/p&gt;

&lt;p&gt;The main thing to keep in mind when working on the library is that there are several consumers, and that the API of the library should remain stable. Breaking changes may complicate the upgrade path of consumers.&lt;/p&gt;

&lt;p&gt;As the platform evolves and newer versions of API’s are adopted by production services it’s also important to keep the clients in the library in sync with new endpoints.&lt;/p&gt;




</description>
      <category>testautomation</category>
      <category>kotlin</category>
      <category>testautomationframew</category>
    </item>
    <item>
      <title>Meet the Captain</title>
      <dc:creator>Joost van Wollingen</dc:creator>
      <pubDate>Sat, 27 Jan 2024 22:52:43 +0000</pubDate>
      <link>https://dev.to/uboot-game/meet-the-captain-18ie</link>
      <guid>https://dev.to/uboot-game/meet-the-captain-18ie</guid>
      <description>&lt;p&gt;Since I’m &lt;strong&gt;no artist&lt;/strong&gt; , we’re starting from AI generated images, and from there try to modify them to fit the game. Today, I started on a first draft for a character: &lt;em&gt;The Captain&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;First I generated some portraits of &lt;em&gt;“seasoned navy captains, with a scar, smoking a cigar, cartoony”&lt;/em&gt;. I’ll have to up my prompt engineering in the coming time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WC1lWx6P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ubootgame.github.io/ubootgame/blog/images/portraits.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WC1lWx6P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://ubootgame.github.io/ubootgame/blog/images/portraits.png" alt="Portraits of the Captain" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is what the Captain could look like according to AI&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I threw the portrait I liked most into &lt;a href="https://www.aseprite.com"&gt;aseprite&lt;/a&gt;, a sprite editor &amp;amp; pixel art tool. It came up as a good tool to do the graphics in for our kind of game, and I got myself a license through &lt;a href="https://www.steampowered.com"&gt;Steam&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My first goal was to take the AI generated still, and make a speech animation. I grabbed the Captain’s mustache and lowerlip, added a frame where these part and painted in some basic teeth. For a draft, in a tool I never used before, it’s good enough for now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GVvkSaLH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://ubootgame.github.io/ubootgame/blog/images/cap_talking.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GVvkSaLH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://ubootgame.github.io/ubootgame/blog/images/cap_talking.gif" alt="More mustache than man" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;More mustache than man&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next, I wanted to simulate some sort of &lt;a href="https://en.wikipedia.org/wiki/Scan_line"&gt;scanlines&lt;/a&gt;, for the videocall sequences where we’d use these portraits. I’ve probably overcomplicated things, used too many layers and animated it clumsily, but the end result I was pretty happy with. Reminds me of those old, green, monochrome monitors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yfuWTL8i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://ubootgame.github.io/ubootgame/blog/images/cap_talking_scanlines.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yfuWTL8i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://ubootgame.github.io/ubootgame/blog/images/cap_talking_scanlines.gif" alt="Scanlines" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Captain uses some old naval technology for video conferencing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finally, I tried my hand at an overlay for the portrait + scanlines, to have somewhat of a border around it, and tried some more animations, such as the blinking light and the scrolling letters. That’s far too clumsy to do neatly in aseprite as far as I can tell for now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M_PsDzEo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://ubootgame.github.io/ubootgame/blog/images/cap_talking_border.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M_PsDzEo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://ubootgame.github.io/ubootgame/blog/images/cap_talking_border.gif" alt="Dukey pick up the phone" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Here’s the Captain on the phone with you, giving orders.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doing these in &lt;a href="https://www.aseprite.com"&gt;aseprite&lt;/a&gt; is a lot of fun, although I should probably take some time to study the tool and read the documentation. For now, I’ve been going by experience from other graphical editors I’ve worked with throughout the years. We’ll get there!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Surfacing</title>
      <dc:creator>Joost van Wollingen</dc:creator>
      <pubDate>Sat, 27 Jan 2024 08:22:42 +0000</pubDate>
      <link>https://dev.to/uboot-game/surfacing-2dlf</link>
      <guid>https://dev.to/uboot-game/surfacing-2dlf</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Lightning cracks, thick rain drops fall down relentlessly, making it almost impossible to see outside. The wind howls around the bridge, rolling the ship in the giant waves. We’re being hunted.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Building in Public
&lt;/h2&gt;

&lt;p&gt;It’s a game we’ve dreamed about for years now. We never started development, but that changes today. At this stage, it’s not much more than a few loosely related thoughts, ideas and experiments we want to run. There is a million things to learn, such as &lt;a href="https://go.dev/"&gt;Golang&lt;/a&gt;, &lt;a href="https://ebitengine.org/"&gt;Ebitenengine&lt;/a&gt;, game design, sound design, music, graphics, &lt;a href="https://www.aseprite.org/"&gt;aseprite&lt;/a&gt;, entity component system, artificial intelligence.&lt;/p&gt;

&lt;p&gt;This blog will be used to document our journey, the things we learn along the way, and the progress the game is making. We’ll be building in public, to keep us on our toes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Game
&lt;/h2&gt;

&lt;p&gt;In the game the player will pilot a destroy-class ship, with a unique, challenging control-scheme. Fights will take place in the air and with submerged enemies. You can expect updates as we refine our thinking around the game, its design and gameplay loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Latest
&lt;/h2&gt;

&lt;p&gt;We publish every build at the following url, fully playable in your browser thanks to WASM !&lt;/p&gt;

&lt;p&gt;Play the game at &lt;a href="https://ubootgame.github.io/ubootgame/"&gt;https://ubootgame.github.io/ubootgame/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>jq for testers</title>
      <dc:creator>Joost van Wollingen</dc:creator>
      <pubDate>Wed, 24 Jan 2024 08:46:56 +0000</pubDate>
      <link>https://dev.to/jpjwolli/jq-for-testers-5bo9</link>
      <guid>https://dev.to/jpjwolli/jq-for-testers-5bo9</guid>
      <description>&lt;p&gt;As test automation engineers we often touch many different tools, protocols, data, and systems. Whatever we need to get the job done. Wrangling data can be quite burdensome, for example when preparing data for a next test or to verify expectations against data retrieved. Data can be in the wrong format, have additional unwanted fields, lack fields, or the receiving system expects a different structure.&lt;/p&gt;

&lt;p&gt;Nowadays a lot of the data that we deal with is JSON. Simple enough to deal with and widely supported by tons of tools. It gets annoying when some of the issues above pop-up and you want to change the data for a lot of tests, or it’s just a lot of data.&lt;/p&gt;

&lt;p&gt;Here is where &lt;a href="https://github.com/jqlang/jq" rel="noopener noreferrer"&gt;&lt;em&gt;jq&lt;/em&gt;&lt;/a&gt; can help. Jq is an &lt;a href="https://github.com/jqlang/jq" rel="noopener noreferrer"&gt;open source command line tool&lt;/a&gt;, that makes it easy to deal with json in all kinds of scenarios. Below I’m sharing a few of the most useful applications I’ve come across for jq.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For the examples in this article I’m using data and endpoints from &lt;a href="https://fakestoreapi.com/" rel="noopener noreferrer"&gt;https://fakestoreapi.com/&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Pretty print &amp;amp; color json
&lt;/h3&gt;

&lt;p&gt;Often systems return &lt;em&gt;minified&lt;/em&gt; json, without white space and line breaks. While a bit more efficient to transmit, it makes it a lot harder to read for humans. Jq can help. Given a piece of json on your clipboard simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pbpaste | jq
&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftgs7b271e7afvib599uc.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%2Ftgs7b271e7afvib599uc.png" alt="pretty printed and colored json from jq" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you pass in JSON to the jq command it will automatically pretty-print and color the input. Nice!&lt;/p&gt;

&lt;h3&gt;
  
  
  Select only one field from an array of objects
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://fakestoreapi.com/users" rel="noopener noreferrer"&gt;https://fakestoreapi.com/users&lt;/a&gt; returns a list of users and their details. To grab only the address fields of each entry:&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://fakestoreapi.com/users | jq '.[].address'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Slice the data
&lt;/h3&gt;

&lt;p&gt;In order to grab the first 3 elements from an array you’d run:&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://fakestoreapi.com/users | jq '.[0:3]'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Construct a new object
&lt;/h3&gt;

&lt;p&gt;Sometimes you want to shuffle the data you have into another structure. jq again makes this easy.&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://fakestoreapi.com/users | jq '.[] | {user: "\(.name.firstname) \(.name.lastname)", phone: .phone}'
&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falwa5lwax214gq6cg7yg.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%2Falwa5lwax214gq6cg7yg.png" alt="jq" width="406" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Count
&lt;/h3&gt;

&lt;p&gt;Calling the length function gets you the number of items in an array or the number of key-value pairs in an object. Very useful if you want to run some quick verifications on the data.&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://fakestoreapi.com/users | jq length
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get a list of all users whose e-mail address contains ‘w’&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://fakestoreapi.com/users|jq 'map(select(.email | contains("w")))'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Count all users with a ‘w’ in their e-mail address&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://fakestoreapi.com/users|jq 'map(select(.email | contains("w")))' | jq length
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There’s a lot more you can do with jq, check out the &lt;a href="https://jqlang.github.io/jq/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; for much, much more you can do with it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pluralsight.pxf.io/75Vj13" rel="noopener noreferrer"&gt;Learn the fundamentals of Test Automation, in my course on Pluralsight- Test Automation: The Big Picture&lt;/a&gt;(affiliate link).&lt;/p&gt;




</description>
    </item>
    <item>
      <title>Catching java.io.IOException: Broken pipe with the help of toxiproxy</title>
      <dc:creator>Joost van Wollingen</dc:creator>
      <pubDate>Sun, 21 Jan 2024 15:33:31 +0000</pubDate>
      <link>https://dev.to/jpjwolli/catching-javaioioexception-broken-pipe-with-the-help-of-toxiproxy-23c8</link>
      <guid>https://dev.to/jpjwolli/catching-javaioioexception-broken-pipe-with-the-help-of-toxiproxy-23c8</guid>
      <description>&lt;p&gt;Recently I’ve moved into a new team, which is responsible for the front- and backend of a backoffice application. The alerting for our applications is configured to trigger whenever log lines come in at the error level.&lt;/p&gt;

&lt;p&gt;As the backend was throwing a lot of &lt;em&gt;java.io.IOException: Broken pipe&lt;/em&gt; exceptions I started to investigate. My team members shared that this error was thrown whenever users navigate away from a page, while the backend is still transmitting data to them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Observability&lt;/em&gt; had not received a lot of attention for this application and the &lt;em&gt;signal to noise ratio&lt;/em&gt; in our logs and alerts was very low. I decided that we needed to stop logging this error, especially because this alert was not &lt;em&gt;actionable:&lt;/em&gt; it is not &lt;em&gt;recoverable&lt;/em&gt;, and there is nothing actually functionally wrong.&lt;/p&gt;

&lt;p&gt;I started setting up a testbed to reproduce the &lt;em&gt;hypothesis&lt;/em&gt; that this exception occurred when the client hangs up unexpectedly.&lt;/p&gt;

&lt;p&gt;I decided to go with the locally running service and toxiproxy. Toxiproxy is an open source project that allows you to sit between client and server and introduce network related issues such as latency, and limited bandwidth.&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%2Fnd97y0muvr16zvjd2e1r.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%2Fnd97y0muvr16zvjd2e1r.png" alt="Toxiproxy sits between client and server" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing toxiproxy
&lt;/h3&gt;

&lt;p&gt;Toxiproxy works with a server component and a cli to configure said server. Installing it is easy enough, simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install toxiproxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting up the toxic
&lt;/h3&gt;

&lt;p&gt;In our case first I set up the toxiproxy server to listen on port 4444 and forward any requests to my application at port 8080. This configuration was named “&lt;em&gt;connectionreset&lt;/em&gt;”.&lt;/p&gt;

&lt;p&gt;Next we added a toxic to this proxy, to limit the data after receiving 1 byte.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;toxiproxy-server &amp;amp;
toxiproxy-cli create -listen localhost:4444 -upstream localhost:8080 connectionreset
toxiproxy-cli toxic add --type limit_data -a bytes=1 connectionreset
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reproducing the broken pipe exception
&lt;/h3&gt;

&lt;p&gt;The plan was to call the service with curl through toxiproxy. On the first attempt the service logged a broken pipe exception, perfect! I started implementing a method to catch this exception and lower the log level. For this we have a RestExceptionHandler class, annotated with &lt;a href="https://www.baeldung.com/exception-handling-for-rest-with-spring#controlleradvice" rel="noopener noreferrer"&gt;@_ControllerAdvice_&lt;/a&gt;. Any exceptions at the API level are handled centrally by that class.&lt;/p&gt;

&lt;p&gt;Because we still want to know if this happens a lot, I also created a metric, which we’d increment every time we caught a broken pipe. That way, if we’d still be able to see if an abnormal amount of exceptions started to occur.&lt;/p&gt;

&lt;p&gt;Then I rebooted the server and tried to call again with another endpoint. Nothing! Not entirely what we expected, as at least there should’ve been an INFO log and an increased metric. Hmm, what’s going on here? The original endpoint I tested with still responded as I expected.&lt;/p&gt;

&lt;p&gt;My first hunch was that somehow the two endpoint controllers were different, and/or the controller advice wasn’t being picked up by one of them. But because I had no trouble with other exceptions handled by the rest exception handler that couldn’t be it. After investigating with Mykola, we figured out the size of the response mattered. Although toxiproxy would kill the connection after receiving the first byte, for small responses the server would’ve already finished sending all the data and not log any errors.&lt;/p&gt;

&lt;p&gt;With this we were satisfied and the test setup with toxiproxy proved to be very useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It allowed me to induce the fault condition&lt;/li&gt;
&lt;li&gt;It allowed me to explore the situations in which the exception was thrown — all from my local machine&lt;/li&gt;
&lt;li&gt;It helped me in verifying the changes to our application to handle broken pipe exceptions more gracefully&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reading material
&lt;/h3&gt;

&lt;p&gt;Here are some of the materials that helped me figure this out.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Shopify/toxiproxy" rel="noopener noreferrer"&gt;https://github.com/Shopify/toxiproxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/bishwapoudel/how-i-fixed-java-io-ioexception-broken-pipe-in-java-wildfly-10-1-86k"&gt;https://dev.to/bishwapoudel/how-i-fixed-java-io-ioexception-broken-pipe-in-java-wildfly-10-1-86k&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/spring-projects/spring-framework/issues/26181" rel="noopener noreferrer"&gt;https://github.com/spring-projects/spring-framework/issues/26181&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://pluralsight.pxf.io/75Vj13" rel="noopener noreferrer"&gt;My Pluralsight course — Test Automation: The Big Picture&lt;/a&gt;(affiliate link),&lt;a href="https://pluralsight.pxf.io/75Vj13" rel="noopener noreferrer"&gt;&lt;/a&gt;covers why fast feedback is so important and what types of test automation you can expect to find out there.&lt;/p&gt;




</description>
    </item>
    <item>
      <title>Evolution of Test Automation for a Monolith</title>
      <dc:creator>Joost van Wollingen</dc:creator>
      <pubDate>Tue, 02 Jan 2024 22:06:16 +0000</pubDate>
      <link>https://dev.to/jpjwolli/evolution-of-test-automation-for-a-monolith-4k4n</link>
      <guid>https://dev.to/jpjwolli/evolution-of-test-automation-for-a-monolith-4k4n</guid>
      <description>&lt;p&gt;The monolith. Dreaded for its sluggishness, tangledness and license costs. Mongering fear in the hearts of developers, who tame it through incantations long lost to the void of attrition. The call for new features and profits overshadowing the long lasting desire to replace it. Its expensive maintenance delegated to consulting shamans, whose native development rituals make little sense to modern man.&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%2F7eeiifh94m18kiv94g72.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%2F7eeiifh94m18kiv94g72.png" alt="monolith" width="512" height="512"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;A menacing monolith. Generated via &lt;a href="https://hotpot.ai/art-generator" rel="noopener noreferrer"&gt;https://hotpot.ai/art-generator&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Deciphering its glyphs, marks and forgotten functionalities we have discovered ways to tolerate its dull presence in our microservices landscape, where heralds sound the progress of technocracy.&lt;/p&gt;

&lt;p&gt;As we continuously push forward, the monolith slowly withers in its corner, remembering the attention it would revel in during the Platform’s early days. Slowly smothered, deconstructed and derelict, it becomes an empty husk, which no longer commands but is instructed. As its decommissioning lurks on the horizon, we review a few test automation patterns applied throughout the years.&lt;/p&gt;

&lt;h3&gt;
  
  
  Out with the Old, in with the New
&lt;/h3&gt;

&lt;p&gt;Initially the testing team of external consultants was tasked with training us in the Ways of the Monolith. SoapUI was the main tool used, with the code written partially in a foreign language, and long, long, long if-else trees and string concatenation of all over the place. The tests focused on the Monolith, mostly ignoring the New Platform. Clearly, this would not do.&lt;/p&gt;

&lt;p&gt;With Kotlin being the main language at our company, and the ambition to have more involvement of developers in test automation, it was an easy choice. We felt a low entry barrier for contributions by developers was important to create a context where ownership of test automation is shared across test and development teams. With &lt;a href="https://kotlinlang.org/docs/java-interop.html" rel="noopener noreferrer"&gt;Kotlins interop&lt;/a&gt; with Java, we’d have access to the full array of test libraries from the Java ecosystem and still get to enjoy the benefits Kotlin brings in terms of conciseness and syntax.&lt;/p&gt;

&lt;h3&gt;
  
  
  Manual Operation Required
&lt;/h3&gt;

&lt;p&gt;Some of the old tests depended on batch jobs to be ran…manually. After the job completed, you could start the next part of the ‘automated’ test. Working with the team managing the Monolith we figured out how to run the batch jobs from code, speeding up the tests and removing the manual element completely. A nice reminder to not settle for mediocre testability in your applications and test automation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Atomic Tests Blew up the System
&lt;/h3&gt;

&lt;p&gt;Atomic tests (of the non-exploding kind) can help you pin-point faster and with more accuracy what the problem is with your SUT. In our case we set out enthusiastically to increase coverage and write more tests. This worked great for the New Platform side of things, whizzing along quickly, creating all the entities we needed for our tests. But the Monolith choked. Queues would fill up, database transactions would get into deadlock, test verifications would timeout and application server instances would disappear as soon as we started increasing the amount of data created by tests.&lt;/p&gt;

&lt;h4&gt;
  
  
  Anti Pattern: Non Atomic Tests
&lt;/h4&gt;

&lt;p&gt;We needed a way to get around the unreliability of the Monolith. Knowing full well that we were simply trading our current problems for a new set of problems, we decided to drop atomic tests in favour of non atomic tests. Instead of creating fresh test data for every operation we’d want to test, we’d create test data once and re-use it for a chain of operations. This way we could alleviate the bottleneck, still get test (some) test results and keep moving forward. There’s a few issues with this approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A failed test means that you won’t have results for all the tests that would’ve run after that test.&lt;/li&gt;
&lt;li&gt;Failing tests mean that you have to investigate not one but many operations to figure out what is wrong. This increased the load on the team, or Test Engineer on Duty. It takes more time to determine the issue.&lt;/li&gt;
&lt;li&gt;Separate parts of the test really need to be separate. If you need data in a specific state for a specific operation you may have to order the tests or create a new test all together after all. Which then increases the pressure on the bottleneck again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having identified all of this upfront we still decided to move on and to transpose the test set to atomic tests again as soon as it was possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparing Notes
&lt;/h3&gt;

&lt;p&gt;During the &lt;a href="https://www.cnpatterns.org/development-design/strangle-monolithic-application" rel="noopener noreferrer"&gt;strangling of the Monolith&lt;/a&gt; there will be a period of time where both the Monolith and the Platform operate together. While extracting functionalities to new applications (part of) the functionality lives on in the Monolith, and production will still depend on the monolithic part functioning. In our case copies of entities were kept in both the New Platform and the Monolith. One strategy we applied here, was to ‘compare notes’ for each test. An entity created in the New Platform must look the same in the Monolith. Any difference should be investigated, as our migration strategy dictated consistency across both.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unlocking Faster Feedback
&lt;/h3&gt;

&lt;p&gt;As we edge closer to decommissioning the Monolith, less and less features depend on it. However, by keeping it in scope for our automated tests we suffer a penalty: slow feedback. Test runs including the Monolith take about 30 mins, and still suffer from unreliable results. Again, there is a trade off to be made.&lt;/p&gt;

&lt;p&gt;As the New Platform is now the main driver of most major processes, feedback on the New Platform has become more important than feedback on the Monolith. Our test set did not make that distinction, and any test run would verify both the New Platform and the Monolith.&lt;/p&gt;

&lt;p&gt;In order to have faster feedback, we made our tests configurable. An environment variable now determines what parts of our non-atomic tests concerning the Monolith can be skipped. This reduced the test lead time to ~5 minutes. Tests with the Monolith included can still be run on demand. A next step is to return to atomic tests and have even more manageable tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  It ain’t pretty but it works
&lt;/h3&gt;

&lt;p&gt;Of course, some of the things described above come with a certain risk. Risk of spending too much time on inspecting flaky tests. Risk of the Monolith failing and us consciously not running the tests for it. Reality is that we don’t always get to work with perfect systems. And that’s ok. Please just don’t apply any of this blindly. Always weigh your options, in relation to your goals and risk appetite. The only reason this worked in my context is because of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A great team of test engineers, with the culture to meticulously check failing tests.&lt;/li&gt;
&lt;li&gt;A shift-left test approach, where a lot of the tests are executed early on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://pluralsight.pxf.io/75Vj13" rel="noopener noreferrer"&gt;If you want to get started with test automation, check out my Pluralsight course — Test Automation: The Big Picture, it’s a perfect starting point!&lt;/a&gt; (affiliate link)&lt;/p&gt;




</description>
      <category>antipattern</category>
      <category>testautomation</category>
      <category>monolith</category>
    </item>
    <item>
      <title>Journalbeat - Error while reading event: failed to get realtime timestamp: 99</title>
      <dc:creator>Joost van Wollingen</dc:creator>
      <pubDate>Fri, 03 Apr 2020 09:29:05 +0000</pubDate>
      <link>https://dev.to/jpjwolli/journalbeat-error-while-reading-event-failed-to-get-realtime-timestamp-99-5a7o</link>
      <guid>https://dev.to/jpjwolli/journalbeat-error-while-reading-event-failed-to-get-realtime-timestamp-99-5a7o</guid>
      <description>&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%2F9wl9mr3972gdwrwkzciw.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%2F9wl9mr3972gdwrwkzciw.png" alt="journalbeat" width="800" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recently I was setting up an instance of Journalbeat to publish journald logging to our ELK stack. I wanted to publish only the logs for a select set of applications, so I was using the following configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- paths: []
seek: cursor
cursor_seek_fallback: tail
include_matches:
- "systemd.unit=name_of_application" #this will not work!
- "systemd.unit=another_application" #this will not work!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, upon restarting Journalbeat, it kept repeating the following error in its logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error while reading event: failed to get realtime timestamp: 99
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I removed the “include_matches”-section everything worked just fine. In the end, I found the answer in this &lt;a href="https://github.com/elastic/beats/issues/11933" rel="noopener noreferrer"&gt;Github issue&lt;/a&gt;: use the full name of the systemd unit, including .service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- paths: []
seek: cursor
cursor_seek_fallback: tail
include_matches:
- "systemd.unit=name_of_application.service"
- "systemd.unit=another_application.service"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






</description>
      <category>elkstack</category>
      <category>journalbeat</category>
      <category>github</category>
      <category>observability</category>
    </item>
    <item>
      <title>Copy text from your VSCode terminal by selecting it</title>
      <dc:creator>Joost van Wollingen</dc:creator>
      <pubDate>Wed, 05 Feb 2020 14:08:05 +0000</pubDate>
      <link>https://dev.to/jpjwolli/copy-text-from-your-vscode-terminal-by-selecting-it-1p62</link>
      <guid>https://dev.to/jpjwolli/copy-text-from-your-vscode-terminal-by-selecting-it-1p62</guid>
      <description>&lt;p&gt;If you are used to working on a terminal a lot you’ve probably come to love the feature to copy the text you select to your clipboard. Recently I’ve started using VSCode more and more and often ran into the issue that my muscle memory tricked me into selecting some text followed by quickly pasting and executing something else entirely because VSCode’s terminal wasn't configured to copy on select. Turns out this feature has been in VSCode since 2018, you just have to enable it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to settings (⌘,)&lt;/li&gt;
&lt;li&gt;Search for terminal.integrated.copyOnSelection&lt;/li&gt;
&lt;li&gt;Check the checkmark&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy copy/pasting!&lt;/p&gt;




</description>
    </item>
    <item>
      <title>How my mistake made the build 20 minutes slower</title>
      <dc:creator>Joost van Wollingen</dc:creator>
      <pubDate>Wed, 05 Feb 2020 11:40:32 +0000</pubDate>
      <link>https://dev.to/jpjwolli/how-my-mistake-made-the-build-20-minutes-slower-a1c</link>
      <guid>https://dev.to/jpjwolli/how-my-mistake-made-the-build-20-minutes-slower-a1c</guid>
      <description>&lt;p&gt;In order to deploy the same version of your code on all environments, it is important to create immutable artifacts of your application and only do deployments using those artifacts. The artifacts should be created by your CI server, to ensure a consistent environment is used to create the artifacts every time. That’s exactly what I was doing the other day for an application consisting out of more than 15 components. Each component needed to be built in Azure DevOps and subsequently published as a Build Artifact.&lt;/p&gt;

&lt;p&gt;The initial version of the pipeline ran over 25 minutes to publish the 15 or so artifacts: NodeJS applications including their node_modules. The task taking the most time was the &lt;a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/publish-build-artifacts?view=azure-devops" rel="noopener noreferrer"&gt;PublishBuildArtifacts task&lt;/a&gt;, some applications took 20 minutes for that step alone — really slow!.&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%2Fpmssy8yvyhsghqwa8gnx.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%2Fpmssy8yvyhsghqwa8gnx.png" alt="the slow build" width="800" height="78"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;24 minutes is definitely too long for a pipeline!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Of course, this operation should be much faster, so I deducted that I wrongly assumed that the PublishBuildArtifacts task would create a ZIP file and than upload that as the artifact. Instead, I think, the task takes every individual file in the folder mentioned and uploads them one by one.&lt;/p&gt;

&lt;p&gt;By adding the ArchiveFiles task the running time for the build was reduced to a total of 1 minute 30 seconds. The longest publish task is now taking ~20 seconds, down from 20+ minutes! All by adding a single task that creates a ZIP file first. Find a snippet below to get started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/media/8d030f5dd409ada653170c6f56a2625c/href" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/8d030f5dd409ada653170c6f56a2625c/href" rel="noopener noreferrer"&gt;https://medium.com/media/8d030f5dd409ada653170c6f56a2625c/href&lt;/a&gt;&lt;/p&gt;




</description>
    </item>
  </channel>
</rss>
