<?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: Ken Hamric</title>
    <description>The latest articles on DEV Community by Ken Hamric (@kdhamric).</description>
    <link>https://dev.to/kdhamric</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%2F863496%2Faead7a62-3599-416d-8932-7bd87d888269.png</url>
      <title>DEV Community: Ken Hamric</title>
      <link>https://dev.to/kdhamric</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kdhamric"/>
    <language>en</language>
    <item>
      <title>Automating Tracetest Tests via Typescript or Javascript</title>
      <dc:creator>Ken Hamric</dc:creator>
      <pubDate>Wed, 21 Feb 2024 17:39:39 +0000</pubDate>
      <link>https://dev.to/kubeshop/automating-tracetest-tests-via-typescript-or-javascript-5407</link>
      <guid>https://dev.to/kubeshop/automating-tracetest-tests-via-typescript-or-javascript-5407</guid>
      <description>&lt;p&gt;A customer recently asked for the ability to run Tracetest tests programmatically from JavaScript or TypeScript so they could execute setup steps directly in code, then fire off a trace-based test. The need to execute setup steps, or to automated the running of Tracetest as part of other automation sequences are common patterns, so we have released a new &lt;a href="https://www.npmjs.com/package/@tracetest/client" rel="noopener noreferrer"&gt;npm package called &lt;code&gt;@tracetest/client&lt;/code&gt;&lt;/a&gt; that allows you to programmatically add and run Tracetest tests.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Want a “codeless” way to write your setup or tear down steps? You can define steps using our test suite capability. Read “&lt;a href="https://tracetest.io/blog/setup-and-teardown-of-tracetest-tests-with-test-suites" rel="noopener noreferrer"&gt;Setup and Teardown of Tracetest Tests with Test Suites&lt;/a&gt;”.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is Trace-based Testing and Why You Should Care?
&lt;/h2&gt;

&lt;p&gt;Before we dive in, let me answer the first question: &lt;strong&gt;“What the heck is Tracetest?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s an observability-enabled testing tool for Cloud Native architectures. Distributed tracing was introduced to empower SREs to troubleshot the complex, interconnected systems being used in todays microservice and FaaS-based architectures. Tracetest leverages these distributed traces as part of testing, providing you with better visibility and testability via a technique known as trace-based testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning by doing!
&lt;/h2&gt;

&lt;p&gt;This guide will focus on how to use the new NPM package by showing a real example running against a publicly accessible test environment. This example solves a common testing problem, externally setting up data in the test environment before running a test. The scenario is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;As a user,
I want to be able to test
our delete Pokemon endpoint
but need to add a Pokemon
via an external POST call first
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will explain the system under test, further discuss the test scenario and explain code for key sections, then have you clone the repo and run the Typescript code yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Test Environment
&lt;/h2&gt;

&lt;p&gt;We are going to use a pre-deployed version of our Pokeshop demo which is sending its telemetry information to Jaeger. This instance is publicly available so you can run tests against it. You can even view the UI at &lt;a href="https://demo-pokeshop.tracetest.io/" rel="noopener noreferrer"&gt;https://demo-pokeshop.tracetest.io/&lt;/a&gt;. The code for this Pokeshop Demo is available at ‣.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Test Scenario
&lt;/h2&gt;

&lt;p&gt;This is the scenario we are going to execute via TypeScript against our Pokeshop test environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add an entity via a POST to a REST endpoint. For this example, we are adding a Pokemon programmatically as a setup step using the Node.js built-in &lt;code&gt;fetch&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;Run a Tracetest &lt;code&gt;delete-pokemon&lt;/code&gt; test using the &lt;code&gt;[@tracetest/client](https://www.npmjs.com/package/@tracetest/client)&lt;/code&gt; &lt;a href="https://www.npmjs.com/package/@tracetest/client" rel="noopener noreferrer"&gt;NPM package&lt;/a&gt;. We will:

&lt;ul&gt;
&lt;li&gt;Authenticate to app.tracetest.io.&lt;/li&gt;
&lt;li&gt;Upsert a delete-pokemon Tracetest test.&lt;/li&gt;
&lt;li&gt;Run the delete-pokemon Tracetest test.&lt;/li&gt;
&lt;li&gt;Print a summary.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The code to execute this scenario is contained in &lt;a href="https://github.com/kubeshop/tracetest/blob/main/examples/setup-of-tracetest-tests/delete_test.ts" rel="noopener noreferrer"&gt;the &lt;code&gt;delete_test.ts&lt;/code&gt; file&lt;/a&gt; from a repo which we will clone and run locally further in this article. First, let’s discuss the code for the key sections that are utilizing the &lt;code&gt;[@tracetest/client](https://www.npmjs.com/package/@tracetest/client)&lt;/code&gt; &lt;a href="https://www.npmjs.com/package/@tracetest/client" rel="noopener noreferrer"&gt;NPM package&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breakdown and Explanation of Key Sections
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Instantiate Tracetest &amp;amp; Authenticate to &lt;a href="http://app.tracetest.io" rel="noopener noreferrer"&gt;app.tracetest.io&lt;/a&gt; with an API Token
&lt;/h3&gt;

&lt;p&gt;This code does a few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instantiates the module.&lt;/li&gt;
&lt;li&gt;Defines an API token - read more about tokens in the included comment.&lt;/li&gt;
&lt;li&gt;Defines the tracetest object using the &lt;code&gt;await Tracetest(TRACETEST_API_TOKEN)&lt;/code&gt; call. We will use this &lt;code&gt;tracetest&lt;/code&gt; object in future calls to interact with Tracetest.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Tracetest&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tracetest/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// To use the @tracetest/client, you must have a token for the environment. This is created on the Settings &lt;/span&gt;
&lt;span class="c1"&gt;// page under Tokens by the administrator for the environment. The token below has been given the 'engineer'&lt;/span&gt;
&lt;span class="c1"&gt;// role in the pokeshop-demo env in the tracetest-demo org so you can create and run tests in this environment.&lt;/span&gt;
&lt;span class="c1"&gt;// Want to read more about setting up tokens? https://docs.tracetest.io/concepts/environment-tokens&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TRACETEST_API_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tttoken_4fea89f6e7fa1500&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Lets use the TRACETEST_API_TOKEN to authenticate the @tracetest/client module...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tracetest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nc"&gt;Tracetest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TRACETEST_API_TOKEN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Upsert the delete-pokemon Test
&lt;/h3&gt;

&lt;p&gt;Open the delete_pokemon.yaml file which contains the delete-pokemon test and upsert it to the current environment. This is similar to running the Tracetest CLI command: &lt;code&gt;tracetest apply test -f delete_pokemon.yaml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Lets pull in the delete-pokemon test from a file&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;deleteTest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delete_pokemon.yaml&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tracetest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deleteTest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command returned a &lt;code&gt;test&lt;/code&gt; object which is used in the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run the delete-pokemon Tracetest Test
&lt;/h3&gt;

&lt;p&gt;Run the test while passing variables. The variable in this example contains the id of the Pokemon to be deleted in the delete-pokemon test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// run deletes pokemon test&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Running the delete-pokemon test...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tracetest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;runTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;variables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;getVariables&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pokemonId&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Print a Summary of the Test Result
&lt;/h3&gt;

&lt;p&gt;Prints a summary of the test result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tracetest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSummary&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Run the TypeScript Script
&lt;/h2&gt;

&lt;p&gt;Enough talking… lets see this TypeScript script run locally. You will need Node and npm installed - see the &lt;a href="https://docs.npmjs.com/downloading-and-installing-node-js-and-npm" rel="noopener noreferrer"&gt;Downloading and installing Node.js and npm&lt;/a&gt; instructions. You should be able to run both &lt;code&gt;node -v&lt;/code&gt; and &lt;code&gt;npm -v&lt;/code&gt; before trying this example.&lt;/p&gt;

&lt;p&gt;First, clone the repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/kubeshop/tracetest
&lt;span class="nb"&gt;cd &lt;/span&gt;tracetest/examples/setup-of-tracetest-tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the  &lt;code&gt;delete_test.ts&lt;/code&gt; file in this directory. You will see the key sections discussed earlier in this article. To run the example, you only need to execute these commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;typescript &lt;span class="nt"&gt;-g&lt;/span&gt;
npm i @tracetest/client
npm i &lt;span class="c"&gt;# to install dev dependencies&lt;/span&gt;
npm run build
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upon running the program, you will see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433235%2FBlogposts%2Ftypescript-announcement%2FUntitled_21_vpwip4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433235%2FBlogposts%2Ftypescript-announcement%2FUntitled_21_vpwip4.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1708433235/Blogposts/typescript-announcement/Untitled_21_vpwip4.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! You successfully ran &lt;code&gt;delete_test.ts&lt;/code&gt; . The &lt;code&gt;tracetest.getSummary()&lt;/code&gt; shows a brief summary of the test and provides a link to the test run on app.tracetest.io. To see the test response, you will need to be a member of this “Pokeshop Demo” environment. To join, click this link:&lt;/p&gt;

&lt;p&gt;➡︎ &lt;a href="https://app.tracetest.io/organizations/ttorg_2179a9cd8ba8dfa5/invites/invite_760904a64b4b9dc9/accept" rel="noopener noreferrer"&gt;&lt;strong&gt;Join the Pokeshop Demo&lt;/strong&gt;&lt;/a&gt; ⬅︎&lt;/p&gt;

&lt;p&gt;You will be prompted to sign in with either your GitHub or Google account. Once logged in, click the “Join organization” button to get access to the Pokeshop demo environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433250%2FBlogposts%2Ftypescript-announcement%2FUntitled_22_utl0jf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433250%2FBlogposts%2Ftypescript-announcement%2FUntitled_22_utl0jf.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1708433250/Blogposts/typescript-announcement/Untitled_22_utl0jf.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great - you are now a member of the organization with access to the Pokeshop demo environment! &lt;/p&gt;

&lt;p&gt;You can then follow the link to the test run, click on the “Test” tab and see the results for the &lt;code&gt;delete-pokemon&lt;/code&gt; test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433252%2FBlogposts%2Ftypescript-announcement%2FUntitled_23_ll549k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433252%2FBlogposts%2Ftypescript-announcement%2FUntitled_23_ll549k.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1708433252/Blogposts/typescript-announcement/Untitled_23_ll549k.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congrats - you successfully ran the example. Want to look at another example? Checkout the &lt;a href="https://docs.tracetest.io/tools-and-integrations/typescript" rel="noopener noreferrer"&gt;Programmatically triggered trace-based tests using Tracetest and TypeScript&lt;/a&gt; quick start guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;Now that you have seen how to run Tracetest tests via your own TypeScript code, you are now ready to create your own tests and embed them in custom flows!&lt;br&gt;
To use Tracetest to test your own environment, follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new &lt;a href="https://docs.tracetest.io/concepts/organizations" rel="noopener noreferrer"&gt;organization&lt;/a&gt; and &lt;a href="https://docs.tracetest.io/concepts/environments" rel="noopener noreferrer"&gt;environment&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Use the environment setup wizard to enable your Tracetest environment to run tests against and collect distributed trace information from your system under test.&lt;/li&gt;
&lt;li&gt;Start creating tests!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Have questions? The devs and I hang out in the &lt;a href="https://dub.sh/tracetest-community" rel="noopener noreferrer"&gt;Tracetest Slack channel&lt;/a&gt; - join, ask, and we will answer!&lt;/p&gt;

</description>
      <category>observability</category>
      <category>testing</category>
      <category>development</category>
      <category>cloudnative</category>
    </item>
    <item>
      <title>Setup and Teardown of Tracetest Tests with Test Suites</title>
      <dc:creator>Ken Hamric</dc:creator>
      <pubDate>Wed, 21 Feb 2024 17:33:44 +0000</pubDate>
      <link>https://dev.to/kubeshop/setup-and-teardown-of-tracetest-tests-with-test-suites-cnn</link>
      <guid>https://dev.to/kubeshop/setup-and-teardown-of-tracetest-tests-with-test-suites-cnn</guid>
      <description>&lt;p&gt;A customer recently asked what the best way to run setup or tear down steps before running a test. Since this is a common pattern, we felt a pair of articles discussing it would be helpful. This article will focus on using the test suite capability to chain together and pass variables between Tracetest tests. &lt;/p&gt;

&lt;p&gt;We also support using the &lt;code&gt;@tracetest/client&lt;/code&gt; NPM package to programmatically execute setup steps and call the Tracetest test as part of a JavaScript or TypeScript program.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Want to write your setup process in JavaScript or TypeScript instead? Read “&lt;a href="//tracetest.io/blog/automating-tracetest-tests-via-typescript-or-javascript"&gt;Automating Tracetest Tests via TypeScript or JavaScript&lt;/a&gt;”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is Trace-based Testing and Why You Should Care?
&lt;/h2&gt;

&lt;p&gt;Before we dive in, let me answer the first question: &lt;strong&gt;“What the heck is Tracetest?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s an observability-enabled testing tool for Cloud Native architectures. Distributed tracing was needed to empower SREs to troubleshot the complex, interconnected systems being used in microservices and FaaS-based architectures. Tracetest can be leveraged in your preproduction environments by DevOps, QAs, or SREs to test critical flows. Since it uses your existing observability tooling, its tests have more visibility into the overall system. This technique is called trace-based testing, and has several compelling advantages: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Makes it easier to write tests, as you can see all the systems involved in the flow.&lt;/li&gt;
&lt;li&gt;Tests can be more powerful and assert on conditions that are not visible to black box tests.&lt;/li&gt;
&lt;li&gt;When troubleshooting failed tests, you have the full distributed trace available, decreasing MTTR.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Handle Setup and Teardown of Tracetest Tests with Test Suites?
&lt;/h2&gt;

&lt;p&gt;Tracetest’s codeless approach for this requirement utilizes &lt;a href="https://docs.tracetest.io/concepts/test-suites" rel="noopener noreferrer"&gt;test suites&lt;/a&gt; to chain together several tests into one comprehensive flow. Tracetest tests have the ability to trigger activity in the system under test, triggering activity based on the following types of calls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP&lt;/li&gt;
&lt;li&gt;GRPC&lt;/li&gt;
&lt;li&gt;Message queue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using this capability, you can run “setup tests” before the main test and “clean up” tests after it.&lt;/p&gt;

&lt;p&gt;This article describes a test scenario, the two tests involved, and provides instructions so you can download and run the examples yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Test Scenario
&lt;/h2&gt;

&lt;p&gt;This test scenario is a common one. Adding an entity so you can then test the deletion of it.&lt;/p&gt;

&lt;p&gt;The system we will be testing if a Pokemon was deleted successfully. You’ll add and delete a Pokemon with two tests. The tests are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adds an entity as a setup step. For this example, we are adding the Pokemon Fearow!&lt;/li&gt;
&lt;li&gt;Run a &lt;code&gt;delete test&lt;/code&gt; to verify that the deletion removes the entity we added in the setup step. This is the main flow we are interested in testing. Hopefully we can say “Goodbye Fearow!”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are going to use a pre-deployed version of our Pokeshop demo which is sending its telemetry information to Jaeger. This instance is publicly available so you can run tests against it.&lt;/p&gt;

&lt;p&gt;You can even &lt;a href="https://demo-pokeshop.tracetest.io/" rel="noopener noreferrer"&gt;view the UI, here&lt;/a&gt;. The code for this Pokeshop Demo is available at &lt;a href="https://github.com/kubeshop/pokeshop" rel="noopener noreferrer"&gt;on GitHub at kubeshop/pokeshop&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To follow the examples and see the code below, clone our main repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/kubeshop/tracetest
&lt;span class="nb"&gt;cd &lt;/span&gt;tracetest/examples/setup-of-tracetest-tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Delete Test
&lt;/h2&gt;

&lt;p&gt;The delete test is contained in the file named &lt;code&gt;delete_pokemon.yaml&lt;/code&gt;. This test does a DELETE call against a specific Pokemon based on the &lt;code&gt;id&lt;/code&gt; of the Pokemon. We are passing the &lt;code&gt;id&lt;/code&gt; of the Pokemon into this test using an environment variable using the syntax &lt;code&gt;${env:pokemon_id}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This trace-based test has four test specifications. The first is a typical assertion you might see with any black box test framework:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Delete returns a 200 status code:&lt;/strong&gt; Ensures the REST API returns a successful status.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next 3, however, leverage the visibility enabled by trace-based testing to look deeper into the execution, allowing you to assert on what actually happened by looking at the data contained in the captured distributed trace: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ensure we are deleting from the Redis cache also&lt;/strong&gt;: A more insightful assertion, and one you cannot make with a normal, black box test.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;All Database Spans: Processing time is less than 10ms&lt;/strong&gt;: Check performance as part of the test so it will fail if a slow query is introduced.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check that number of deleted rows from Postgres is one&lt;/strong&gt;: Verify the delete actually occurs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the &lt;code&gt;delete_pokemon.yaml&lt;/code&gt; test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;delete-pokemon&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Delete Pokemon&lt;/span&gt;
  &lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
    &lt;span class="na"&gt;httpRequest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DELETE&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://demo-pokeshop.tracetest.io/pokemon/${env:pokemon_id}&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Content-Type&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
  &lt;span class="na"&gt;specs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="general" name="Tracetest trigger"]&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Delete returns a 200 status code&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:tracetest.response.status = &lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="database" db.system="redis" db.operation="del" db.redis.database_index="0"]&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ensure we are deleting from the redis cache also&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:tracetest.selected_spans.count = &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="database"]&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;All&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Database&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Spans:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Processing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;time&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;less&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;than&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;10ms"&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:tracetest.span.duration &amp;lt; 10ms&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="database" name="delete pokeshop.pokemon" db.system="postgres" db.name="pokeshop" db.user="ashketchum" db.operation="delete" db.sql.table="pokemon"]&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check that number of deleted rows from Postgres is one&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:db.result = &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, lets look at the setup step which we will run before to add the Pokemon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Another Tracetest Test to Set up the Data
&lt;/h2&gt;

&lt;p&gt;We can define a new test to create the Pokemon, and then chain the creation and deletion test together within a test suite. First, let’s look at the &lt;code&gt;setup_pokemon.yaml&lt;/code&gt; test. It is fairly basic, with 3 primary areas of interest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is doing a &lt;code&gt;POST&lt;/code&gt; against the &lt;code&gt;/pokemon&lt;/code&gt; endpoint and passing body data to create the Pokemon.&lt;/li&gt;
&lt;li&gt;We are checking for a 201 response from this &lt;code&gt;POST&lt;/code&gt; to ensure the creation of the Pokemon worked. This is just a basic sanity check so the entire test suite will fail if something goes wrong in this setup step.&lt;/li&gt;
&lt;li&gt;We are getting the &lt;code&gt;id&lt;/code&gt; of the Pokemon by selecting data returned in the trace, parsing it with a &lt;code&gt;json_path&lt;/code&gt; statement, and assigning it to the output variable &lt;code&gt;pokemon_id&lt;/code&gt;. This is enabled with Tracetest’s &lt;a href="https://docs.tracetest.io/web-ui/creating-test-outputs" rel="noopener noreferrer"&gt;test output&lt;/a&gt; capability.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;setup-pokemon&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Pokemon&lt;/span&gt;
  &lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
    &lt;span class="na"&gt;httpRequest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://demo-pokeshop.tracetest.io/pokemon&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="nv"&gt;  &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;fearow&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="nv"&gt;  &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;normal,flying&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="nv"&gt;  &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;imageUrl&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/22.png&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="nv"&gt;  &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;isFeatured&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Content-Type&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
  &lt;span class="na"&gt;specs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="general" name="Tracetest trigger"]&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check to see the post worked&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:tracetest.response.status = &lt;/span&gt;&lt;span class="m"&gt;201&lt;/span&gt;
  &lt;span class="na"&gt;outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pokemon_id&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="general" name="Tracetest trigger"]&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;attr:tracetest.response.body| json_path '$.id'&lt;/span&gt;
  &lt;span class="na"&gt;skipTraceCollection&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Combining the Two Tests into a Test Suite
&lt;/h2&gt;

&lt;p&gt;We can then create a test suite, include the &lt;code&gt;setup_pokemon.yaml&lt;/code&gt; test as the first to run, then call our main test, &lt;code&gt;delete_pokemon.yaml&lt;/code&gt;. &lt;a href="https://docs.tracetest.io/web-ui/creating-test-suites" rel="noopener noreferrer"&gt;Creating test suites is covered in our docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When you have finished creating a test suite, the automate tab provides the YAML definition for the suite. Below is the definition for the &lt;code&gt;delete_test_suite.yaml&lt;/code&gt; test suite we created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TestSuite&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Delete with Setup&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;A test of the deletion end point with setup test which adds the pokemon as a setup step.&lt;/span&gt;
  &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;setup-pokemon&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;delete-pokemon&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;setup-pokemon&lt;/code&gt; test outputs the &lt;code&gt;pokemon_id&lt;/code&gt; variable, and the &lt;code&gt;delete-pokemon&lt;/code&gt; test expects a variable with this name via the &lt;code&gt;${env:pokemon_id}&lt;/code&gt;. With this syntax, when you run them as part of a test suite the first test will automatically pass the value and the second test will consume it. This lets the &lt;code&gt;delete-pokemon&lt;/code&gt; test know to delete the Pokemon that was created in the &lt;code&gt;setup-pokemon&lt;/code&gt; setup test.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do we Run the Example?
&lt;/h3&gt;

&lt;p&gt;Enough talking - lets see this test suite run! First, clone the repo if you did not earlier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/kubeshop/tracetest
&lt;span class="nb"&gt;cd &lt;/span&gt;tracetest/examples/setup-of-tracetest-tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are going to do several steps so we can see the test suite run:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Join the Tracetest &lt;strong&gt;&lt;em&gt;pokeshop-demo&lt;/em&gt;&lt;/strong&gt; environment so you can run and view your tests&lt;/li&gt;
&lt;li&gt;Install the Tracetest command line tool (CLI) so you can upload the two tests&lt;/li&gt;
&lt;li&gt;Use the CLI to run the test suite and view the test output&lt;/li&gt;
&lt;li&gt;Open the test suite in &lt;a href="https://app.tracetest.io" rel="noopener noreferrer"&gt;Tracetest&lt;/a&gt; and examine the results from the suite and the delete test.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let’s Do It!
&lt;/h2&gt;

&lt;p&gt;Let’s run the test suite inside of the &lt;strong&gt;&lt;em&gt;pokeshop-demo&lt;/em&gt;&lt;/strong&gt; environment which we have available as part of our &lt;strong&gt;&lt;em&gt;tracetest-demo&lt;/em&gt;&lt;/strong&gt; organization at &lt;a href="https://app.tracetest.io" rel="noopener noreferrer"&gt;&lt;code&gt;app.tracetest.io&lt;/code&gt;&lt;/a&gt;. In order to connect and run tests in this environment, you will need to join it with this link:&lt;/p&gt;

&lt;p&gt;➡︎ &lt;a href="https://app.tracetest.io/organizations/ttorg_2179a9cd8ba8dfa5/invites/invite_760904a64b4b9dc9/accept" rel="noopener noreferrer"&gt;&lt;strong&gt;Join the Pokeshop Demo&lt;/strong&gt;&lt;/a&gt; ⬅︎&lt;/p&gt;

&lt;p&gt;You will be promoted to sign in with either your GitHub or Google account. Once logged in, click the “Join organization” button to get access to the Pokeshop demo environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433981%2FBlogposts%2Ftypescript-announcement%2FUntitled_24_hzhl2d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433981%2FBlogposts%2Ftypescript-announcement%2FUntitled_24_hzhl2d.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1708433981/Blogposts/typescript-announcement/Untitled_24_hzhl2d.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great - you are now a member of the organization with access to the Pokeshop demo environment! We will be running the test suite against this environment from the command line interface (CLI) tool, so you will need to install the CLI. The instructions are &lt;a href="https://docs.tracetest.io/getting-started/installation" rel="noopener noreferrer"&gt;documented here&lt;/a&gt;, but for Mac, you can just type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;kubeshop/tracetest/tracetest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, tell the command line what organization and environment we want to issue commands against by typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tracetest configure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will need to select the &lt;strong&gt;&lt;em&gt;tracetest-demo&lt;/em&gt;&lt;/strong&gt; organization and the &lt;strong&gt;&lt;em&gt;pokeshop-demo&lt;/em&gt;&lt;/strong&gt; environment as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433981%2FBlogposts%2Ftypescript-announcement%2Fselect-org-env_dwhuuh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433981%2FBlogposts%2Ftypescript-announcement%2Fselect-org-env_dwhuuh.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1708433981/Blogposts/typescript-announcement/select-org-env_dwhuuh.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’re ready to add the two tests to this environment so they can be run by the test suite. The tests are part of the repo you cloned, so just type the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tracetest apply &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; setup_pokemon.yaml
tracetest apply &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; delete_pokemon.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that the definitions for the two tests have been created in the test environment, you can run the test suite, which chains the two tests together and executes them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tracetest run testsuite &lt;span class="nt"&gt;-f&lt;/span&gt; delete_test_suite.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the output you should see after running the test suite:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433981%2FBlogposts%2Ftypescript-announcement%2FUntitled_25_fc52rz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433981%2FBlogposts%2Ftypescript-announcement%2FUntitled_25_fc52rz.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1708433981/Blogposts/typescript-announcement/Untitled_25_fc52rz.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This output shows that the “Delete with Setup” test suite was run successfully. It also shows the two tests that were run as part of the suite. Both the suite and the two tests show links which will allow you to view the results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433980%2FBlogposts%2Ftypescript-announcement%2FUntitled_26_t4zqgv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433980%2FBlogposts%2Ftypescript-announcement%2FUntitled_26_t4zqgv.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1708433980/Blogposts/typescript-announcement/Untitled_26_t4zqgv.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here is what you will see if you click on the Delete Pokemon test results and click to see the “Test” tab results. It shows the 4 test specs you are running as part of the delete test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433252%2FBlogposts%2Ftypescript-announcement%2FUntitled_23_ll549k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1708433252%2FBlogposts%2Ftypescript-announcement%2FUntitled_23_ll549k.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1708433252/Blogposts/typescript-announcement/Untitled_23_ll549k.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You have walked through the process needed to create two tests, combine them into a test suite, and pass a test output from one to another. This is an easy way to chain tests together in order to perform setup tasks. &lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;While I did not show an example, you can use the same test suite technique to run a teardown or cleanup process after a test. Rename the processes “teardown” rather than “setup” and run them after the test! 😃&lt;/p&gt;

&lt;p&gt;Now that you have seen how to run setup steps with test suites, you are now ready to create your own tests! Follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new &lt;a href="https://docs.tracetest.io/concepts/organizations" rel="noopener noreferrer"&gt;organization&lt;/a&gt; and &lt;a href="https://docs.tracetest.io/concepts/environments" rel="noopener noreferrer"&gt;environment&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Use the environment setup wizard to enable your Tracetest environment to run tests against and collect distributed trace information from your system under test.&lt;/li&gt;
&lt;li&gt;Start creating tests!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To learn how to automate this same setup process in JavaScript or TypeScript instead, check out part 2 of called “&lt;a href="//tracetest.io/blog/automating-tracetest-tests-via-typescript-or-javascript"&gt;Automating Tracetest Tests via Typescript or Javascript&lt;/a&gt;”.&lt;/p&gt;

&lt;p&gt;Have questions? The devs and I hang out in the &lt;a href="https://dub.sh/tracetest-community" rel="noopener noreferrer"&gt;Tracetest Slack channel&lt;/a&gt; - join, ask, and we will answer!&lt;/p&gt;

</description>
      <category>observability</category>
      <category>testing</category>
      <category>development</category>
      <category>cloudnative</category>
    </item>
    <item>
      <title>The Lord of Playwright: The Two Traces</title>
      <dc:creator>Ken Hamric</dc:creator>
      <pubDate>Thu, 08 Feb 2024 17:26:55 +0000</pubDate>
      <link>https://dev.to/kubeshop/the-lord-of-playwright-the-two-traces-358l</link>
      <guid>https://dev.to/kubeshop/the-lord-of-playwright-the-two-traces-358l</guid>
      <description>&lt;h2&gt;
  
  
  Test and Debug Critical End to End Flows with Playwright and OpenTelemetry
&lt;/h2&gt;

&lt;p&gt;Today is a tale of two traces!&lt;/p&gt;

&lt;p&gt;Playwright Traces and OpenTelemetry Traces are brought together to create one test to rule them all. Well actually, to test both your front end AND back end in one swing.&lt;/p&gt;

&lt;p&gt;Using the power of Playwright to drive tests of your critical flows from the browser, this integration extends your Playwright tests to leverage OpenTelemetry and trace-based testing.&lt;/p&gt;

&lt;p&gt;You can now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Test, in depth!&lt;/strong&gt; Apply assertions against the entire front end application AND back end application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Troubleshoot failed tests, with traces.&lt;/strong&gt; Both Playwright traces and OpenTelemetry-based distributed traces.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stop the blame game.&lt;/strong&gt; With a view of the the entire flow, and data from both Playwright and distributed traces, quickly determine the cause of the failure, enabling you to easily identify the developer that can help finish the quest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be the hero and give your developer all the data.&lt;/strong&gt; Examine both Playwright traces and OpenTelemetry traces, all from one test. The devs will love, admire and respect you for it!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complete the quest with better observability!&lt;/strong&gt; As tracing data from instrumentation is used to build trace-based tests, developers will want to add more insightful and meaningful instrumentation. See your ability to fight bugs in your production system enhanced when armed with better observability data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re eager to start, these &lt;a href="https://docs.tracetest.io/tools-and-integrations/playwright" rel="noopener noreferrer"&gt;instructions&lt;/a&gt; provide a full example, with an instrument Cloud Native app! Want to see some examples right away of Tracetest infused Playwright tests? &lt;a href="https://app.tracetest.io/organizations/ttorg_2179a9cd8ba8dfa5/invites/invite_760904a64b4b9dc9/accept" rel="noopener noreferrer"&gt;Join the environment&lt;/a&gt; and look at the three Playwright tests, and tune in for &lt;a href="https://www.linkedin.com/events/7160964167384850432/comments/" rel="noopener noreferrer"&gt;a live workshop on February 15th&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=mmOAZxYdTYw" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=mmOAZxYdTYw&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Heroes
&lt;/h2&gt;

&lt;p&gt;To start, lets identify the heroes involved in this saga.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; is the fastest growing web testing framework. Playwright enables end-to-end (E2E) tests to be created by synthetically driving a headless browser session and enabling assertions to verify the system performs as expected. With Playwright traces, you can review a test after the script has run and identify exactly what occurred. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://opentelemetry.io/" rel="noopener noreferrer"&gt;OpenTelemetry&lt;/a&gt; is the fastest growing &lt;a href="https://www.cncf.io/" rel="noopener noreferrer"&gt;Cloud Native Computing Foundation (CNCF)&lt;/a&gt; project. It standardizes the instrumentation and collection of traces, metrics, and logs from applications, and is supported by all the major observability projects, languages, and tools. One standard to rule them all!&lt;/p&gt;

&lt;p&gt;Lastly, located in a quiet shire at the edge of the world is a newcomer to the scene, &lt;a href="https://tracetest.io/" rel="noopener noreferrer"&gt;Tracetest&lt;/a&gt;. Unassuming, but able to wield the power of trace-base testing and OpenTelemetry traces to shine a light in the black box, revealing any hidden gremlins, orcs or nasty spiders (Shelob anybody?) lurking in the dark places.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1707406260%2FBlogposts%2Fplaywright-announcement%2FUntitled_17_qpjsmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1707406260%2FBlogposts%2Fplaywright-announcement%2FUntitled_17_qpjsmw.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1707406260/Blogposts/playwright-announcement/Untitled_17_qpjsmw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Quest: Test the Untestable - Complex, Cloud Native Systems
&lt;/h2&gt;

&lt;p&gt;While capable of doing much good, Cloud Native systems have introduced a level of complexity heretofore not seen in the West. Or the East.&lt;/p&gt;

&lt;p&gt;Microservices, created by different races, in different places. Elves, Dwarves, Men… or at least C#, Go, and React developers, working from afar, from office or from home. Separated into teams, rarely talking, with distrust of the other’s strange ways and weird coding practices. Can anybody bring these groups together?&lt;/p&gt;

&lt;p&gt;The challenge falls to the pre-deployment team, who, like the hero Aragorn, a.k.a. Strider, go by several names. DevOps Engineer. SRE. Cloud, Automation, Infrastructure, or CI/CD Engineer. Their role is to bring together these pieces into a coherent, working whole, that is prepared and ready for the rigors of a production environment and the ultimate challenge - Customers! But what can they place their hopes in? &lt;/p&gt;

&lt;h2&gt;
  
  
  End-to-End Tests!
&lt;/h2&gt;

&lt;p&gt;Yes - true end-to-end tests are the answer. Use Playwright to cover the critical flows in the cloak of actions and assertions, testing to make sure the interactions driven from the browser will return expected results. Catch the errors in your CI/CD flow before deploying. But is this enough? &lt;/p&gt;

&lt;p&gt;No, for evil lurks in the back end also. The Go and C# developers have complex and mysterious ways.&lt;/p&gt;

&lt;p&gt;While the API gateway may return a 200 to the browser, deep in the system, asynchronous gRPC processes may be timing out or returning error status codes. Systems may be using wrong versions of specifications, and processes may not be listening to the correct messages from your Kafka queue. Critical back-end flows, like sending the email on sign up or writing to the database fast enough may not be occurring.&lt;/p&gt;

&lt;p&gt;All hidden from the benevolent view of your Playwright tests by a black box, containing other black boxes, with many differing technologies and arcane logic hidden within.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flip the Light Switch on the Black Box(es)
&lt;/h2&gt;

&lt;p&gt;Much like carrying a vial of the Light of Earendil's Star, embedding a trace-based test into your Playwright test allows you to see the surrounding dangers lurking in your system. But also to set assertions that verify the correct operation of the complete system. What does this magic look like in code?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Tracetest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Types&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tracetest/playwright&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TRACETEST_API_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tracetest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TracetestPlaywright&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;serial&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;definition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
  type: Test
  spec:
    id: UGxheXdyaWdodDogaW1wb3J0cyBhIHBva2Vtb24=
    name: "Playwright: imports a pokemon"
    trigger:
      type: playwright
    specs:
    - selector: span[tracetest.span.type="http"] span[tracetest.span.type="http"]
      name: "All HTTP Spans: Status  code is 200"
      assertions:
      - attr:http.status_code   =   200
    - selector: span[tracetest.span.type="database"]
      name: "All Database Spans: Processing time is less than 100ms"
      assertions:
      - attr:tracetest.span.duration &amp;lt; 2s
    outputs:
    - name: MY_OUTPUT
      selector: span[tracetest.span.type="general" name="Tracetest trigger"]
      value: attr:name
    `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;beforeAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;tracetest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nc"&gt;Tracetest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TRACETEST_API_TOKEN&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;tracetest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setOptions&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Playwright: imports a pokemon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tracetest&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// optional step to break the playwright script in case a Tracetest test fails&lt;/span&gt;
&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;afterAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;testInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;testInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tracetest&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Playwright: creates a pokemon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pokeshop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text=Add&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Charizard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Flying&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Image URL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://upload.wikimedia.org/wikipedia/en/1/1f/Pok%C3%A9mon_Charizard_art.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OK&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;exact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Playwright: imports a pokemon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pokeshop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBeTruthy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text=Import&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ID&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OK&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;exact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Playwright: deletes a pokemon&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-cy="pokemon-list"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-cy="pokemon-card"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-cy="pokemon-card"] [data-cy="delete-pokemon-button"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Track the Uruk-hai (or other Bugs) using Traces
&lt;/h2&gt;

&lt;p&gt;In much the same way that Aragorn used footprints, a dropped elven brooch, and other traces to hunt the Uruk-hai across the stretches of Middle Earth, the entire team can benefit from the dual traces left as artifacts from these Tracetest enhanced Playwright tests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1707406317%2FBlogposts%2Fplaywright-announcement%2FUntitled_18_rt8cum.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1707406317%2FBlogposts%2Fplaywright-announcement%2FUntitled_18_rt8cum.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1707406317/Blogposts/playwright-announcement/Untitled_18_rt8cum.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use the Playwright traces to see exactly what was occurring in the browser, step back in time to see the browser state between each action, and view a video of the entire flow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1707406452%2FBlogposts%2Fplaywright-announcement%2Ftrace.playwright.dev__trace_blob_3Ahttps_3A_2F_2Ftrace.playwright.dev_2F809fb5c2-f517-43a6-93ae-9740260476d0_traceFileName_trace.zip_1_1_nb4bkn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1707406452%2FBlogposts%2Fplaywright-announcement%2Ftrace.playwright.dev__trace_blob_3Ahttps_3A_2F_2Ftrace.playwright.dev_2F809fb5c2-f517-43a6-93ae-9740260476d0_traceFileName_trace.zip_1_1_nb4bkn.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1707406452/Blogposts/playwright-announcement/trace.playwright.dev__trace_blob_3Ahttps_3A_2F_2Ftrace.playwright.dev_2F809fb5c2-f517-43a6-93ae-9740260476d0_traceFileName_trace.zip_1_1_nb4bkn.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, hop into the Tracetest test run. View the full distributed trace, showing the trace spans and attributes captured from both the browser and across your back-end services. See exactly where the trace-based test assertions failed, and inspect the services above and below this point.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1707406476%2FBlogposts%2Fplaywright-announcement%2FUntitled_19_tqy0jo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1707406476%2FBlogposts%2Fplaywright-announcement%2FUntitled_19_tqy0jo.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1707406476/Blogposts/playwright-announcement/Untitled_19_tqy0jo.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With both types of traces, it will be much easier to test for failures across the entire system. Once a test fails, the wealth of data will enable you to identify the area in the system that is causing the problem and quickly assign the bug to the proper team. By providing that team with the same set of traces, they will easily be able to rectify the issue, improving the time to resolve and push a correction. &lt;/p&gt;

&lt;h2&gt;
  
  
  Shine a Light in the Black Box with OpenTelemetry &amp;amp; Tracetest
&lt;/h2&gt;

&lt;p&gt;Much in the same way the pieces of the sword Andúril were forged together from the shards of Narsil to serve Aragorn, modern day heroes in DevOps, Observability, and SRE teams can combine OpenTelemetry, Playwright, and Tracetest to produce a tool to bring peace and harmony to Middle Earth… or at least to your distributed system. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Wv38LNleUpE" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=Wv38LNleUpE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Want to undertake this quest? Do you think you’re ready? You will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To use Playwright for your front-end tests. &lt;a href="https://tracetest.io/blog/cloud-native-observability-and-cypress-an-unlikely-marriage" rel="noopener noreferrer"&gt;Using Cypress instead? Check this out.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Have observability, that hopefully works and plays well with the OpenTelemetry standard, configured for your back-end systems so you can produce distributed traces.&lt;/li&gt;
&lt;li&gt;Use the OpenTelemetry browser instrumentation in your front-end app.&lt;/li&gt;
&lt;li&gt;Sign up for an account on &lt;a href="https://app.tracetest.io/" rel="noopener noreferrer"&gt;Tracetest&lt;/a&gt; so you can run trace-based tests.&lt;/li&gt;
&lt;li&gt;See the instructions on how to &lt;a href="https://docs.tracetest.io/tools-and-integrations/playwright" rel="noopener noreferrer"&gt;include Tracetest libraries in your Playwright tests&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These &lt;a href="https://docs.tracetest.io/tools-and-integrations/playwright" rel="noopener noreferrer"&gt;instructions&lt;/a&gt; provide a full example, with an instrument Cloud Native app, an OpenTelemetry instrumented React front end, and Playwright tests with Tracetest included.&lt;/p&gt;

&lt;p&gt;Want to see some examples of these Tracetest infused Playwright tests? We are running these tests in our demo environment. &lt;a href="https://app.tracetest.io/organizations/ttorg_2179a9cd8ba8dfa5/invites/invite_760904a64b4b9dc9/accept" rel="noopener noreferrer"&gt;Join the environment&lt;/a&gt; and look at the three Playwright tests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1707406503%2FBlogposts%2Fplaywright-announcement%2FUntitled_20_sufdv9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1707406503%2FBlogposts%2Fplaywright-announcement%2FUntitled_20_sufdv9.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1707406503/Blogposts/playwright-announcement/Untitled_20_sufdv9.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have questions? Join the discussion with the nerds (yes, we like LOTR…) that created this supernatural fusion of Playwright and OpenTelemetry in the &lt;a href="https://dub.sh/tracetest-community" rel="noopener noreferrer"&gt;Tracetest Slack channel&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>observability</category>
      <category>testing</category>
      <category>playwright</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Cloud Native Observability and Cypress - an Unlikely Marriage</title>
      <dc:creator>Ken Hamric</dc:creator>
      <pubDate>Fri, 26 Jan 2024 00:20:32 +0000</pubDate>
      <link>https://dev.to/kubeshop/cloud-native-observability-and-cypress-an-unlikely-marriage-4m7o</link>
      <guid>https://dev.to/kubeshop/cloud-native-observability-and-cypress-an-unlikely-marriage-4m7o</guid>
      <description>&lt;p&gt;OpenTelemetry and distributed tracing are critical in enabling troubleshooting and monitoring of your complex, distributed, Cloud Native application.&lt;/p&gt;

&lt;p&gt;Cypress is a powerful tool for testing front-end applications, enabling quick and confident releases of front-end changes. Imagine if you could combine Cypress with distributed traces.&lt;/p&gt;

&lt;p&gt;Now you can! Use distributed traces directly in your Cypress tests to cover the entire distributed system, including both the front end and back end, with trace-based tests. Here’s how Tracetest and Cypress fell in love. 👇&lt;/p&gt;

&lt;h2&gt;
  
  
  Tracetest ❤️ Cypress
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://docs.tracetest.io/tools-and-integrations/cypress/" rel="noopener noreferrer"&gt;Tracetest integration with Cypress&lt;/a&gt; provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full observability.&lt;/strong&gt; Cypress allows you to visually debug test runs. With a distributed trace captured with each test run, you will also have visibility of exactly what happened across the full front end and back end system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster MTTR for failed tests.&lt;/strong&gt; Having full observability will allow you to quickly identify the root cause of failed tests, determine whether the problem is in the frontend or backend, and  easily identify the correct team to fix the problem. Armed with data from both Cypress and the distributed trace, the team correcting the bug will have the necessary information to find a solution quickly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actual end-to-end tests.&lt;/strong&gt; The industry sometimes calls front end tests ‘end to end’, but they are not. Frontend tests can fully test the front end, and even assert on values returned by API calls, but it cannot verify deeply. In today’s asynchronous, message-based architectures, an API calls often initiates a full process, but quickly returns a status code of 200 to say ‘we have the request’. It then relies on multiple backend systems, developed by different teams, to properly execute a flow. Checking that the full process works as expected is an actually end-to-end test. Trace-based tests leverage the visibility empowered by a distributed trace to allow assertions to be placed on the systems through out the flow, providing actual end-to-end testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increased confidence to deploy.&lt;/strong&gt; With your ‘golden paths’ covered by real end-to-end tests, your teams can release with confidence, knowing the tests running as part of your CI/CD process are ensuring critical flows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, the marriage has happened, and we would like to invite you to attend the reception party!&lt;/p&gt;

&lt;p&gt;Tracetest, the leading trace-based test tool, now works directly with your current Cypress tests to fully test your instrumented application. Bring your favorite observability tracing backend, such as Jaeger, Tempo, Honeycomb, AWS X-ray, Dynatrace, Sumo Logic, or &lt;a href="https://tracetest.io/integrations" rel="noopener noreferrer"&gt;9 others&lt;/a&gt; to the event, and let’s party!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/yDXoa8znTQQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Show Me The Wedding Photos!
&lt;/h2&gt;

&lt;p&gt;Let’s look at the rich artifacts provided by these observability enabled Cypress tests.&lt;/p&gt;

&lt;p&gt;First, you get the rich results provided by a Cypress test:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1705666619%2FBlogposts%2Fcloud-native-observability-cypress-unlikely-marriage%2Fcypress_zfzxsv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1705666619%2FBlogposts%2Fcloud-native-observability-cypress-unlikely-marriage%2Fcypress_zfzxsv.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1705666619/Blogposts/cloud-native-observability-cypress-unlikely-marriage/cypress_zfzxsv.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Second, you get a distributed trace, showing entire process flow provided by instrumentation in your frontend and backend:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1705666620%2FBlogposts%2Fcloud-native-observability-cypress-unlikely-marriage%2Ftrace_dbzieq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1705666620%2FBlogposts%2Fcloud-native-observability-cypress-unlikely-marriage%2Ftrace_dbzieq.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1705666620/Blogposts/cloud-native-observability-cypress-unlikely-marriage/trace_dbzieq.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, using trace-based testing assertions, you can have your Cypress test also verify the proper execution of the full system:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1705666619%2FBlogposts%2Fcloud-native-observability-cypress-unlikely-marriage%2Ftracetest_ldqyae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1705666619%2FBlogposts%2Fcloud-native-observability-cypress-unlikely-marriage%2Ftracetest_ldqyae.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1705666619/Blogposts/cloud-native-observability-cypress-unlikely-marriage/tracetest_ldqyae.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As shown, trace-based tests can assert the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the JavaScript bundle in the UI loads in less than 300 ms.&lt;/li&gt;
&lt;li&gt;All HTTP internal calls between systems returned a successful status code.&lt;/li&gt;
&lt;li&gt;Check to make sure a particular service received a message and processed it.&lt;/li&gt;
&lt;li&gt;See if a call to an external service returned the proper value.&lt;/li&gt;
&lt;li&gt;See if a particular, or all, database calls take less than 100 ms.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these assertions created and included in the Cypress test, the test now can assert across the entire system, verifying both functionality and performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  What To Bring to the Reception Party?
&lt;/h2&gt;

&lt;p&gt;There are a few requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use Cypress for your frontend tests. If you use Playwright… stayed tuned for an upcoming event, as this particular party is not for you!&lt;/li&gt;
&lt;li&gt;Have observability, that hopefully works and plays well with the OpenTelemetry standard, configured for your backend systems so you can produce distributed traces.&lt;/li&gt;
&lt;li&gt;Use the OpenTelemetry browser instrumentation in your frontend app.&lt;/li&gt;
&lt;li&gt;Sign up for an account on &lt;a href="https://app.tracetest.io/" rel="noopener noreferrer"&gt;Tracetest&lt;/a&gt; so you can run trace-based tests.&lt;/li&gt;
&lt;li&gt;See the instructions on how to &lt;a href="https://docs.tracetest.io/tools-and-integrations/cypress/" rel="noopener noreferrer"&gt;include Tracetest libraries in your Cypress tests&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://docs.tracetest.io/tools-and-integrations/cypress/" rel="noopener noreferrer"&gt;instructions&lt;/a&gt; provide a full example, with an instrument cloud native app, an OTel instrumented react front end, and Cypress tests with Tracetest included. This is an example of a Cypress test which includes a trace-based test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Tracetest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Types&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@tracetest/cypress&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TRACETEST_API_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TRACETEST_API_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tracetest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TracetestCypress&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;definition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
type: Test
spec:
  id: aW1wb3J0cyBhIHBva2Vtb24=
  name: imports a pokemon
  trigger:
    type: cypress
  specs:
  - selector: span[tracetest.span.type="http"] span[tracetest.span.type="http"]
    name: "All HTTP Spans: Status  code is 200"
    assertions:
    - attr:http.status_code   =   200
  - selector: span[tracetest.span.type="database"]
    name: "All Database Spans: Processing time is less than 100ms"
    assertions:
    - attr:tracetest.span.duration &amp;lt; 2s
  outputs:
  - name: MY_OUTPUT
    selector: span[tracetest.span.type="general" name="Tracetest trigger"]
    value: attr:name
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Home&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;defaultCommandTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60000&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Tracetest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TRACETEST_API_TOKEN&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;tracetest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;tracetest&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setOptions&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;imports a pokemon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;done&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;onBeforeLoad&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;win&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;tracetest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;win&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// uncomment to wait for trace tests to be done&lt;/span&gt;
  &lt;span class="nf"&gt;after&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;tracetest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;done&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;create a pokemon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-cy="create-pokemon-button"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-cy="create-pokemon-modal"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pikachu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Electric&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#imageUrl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://oyster.ignimgs.com/mediawiki/apis.ign.com/pokemon-blue-version/8/89/Pikachu.jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OK&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;imports a pokemon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-cy="import-pokemon-button"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-cy="import-pokemon-form"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[id="id"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OK&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;force&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;deletes a pokemon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-cy="pokemon-list"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;be.visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-cy="pokemon-card"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-cy="delete-pokemon-button"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Attending the Reception Party
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/events/7153780303713447937/comments/" rel="noopener noreferrer"&gt;Tune in live for a webinar workshop on January 24th at 9am PT (12pm ET)&lt;/a&gt; to learn hands-on how to enhance your existing Cypress tests with trace-based testing!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/k0d_ap5jatU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  A Promising Union
&lt;/h2&gt;

&lt;p&gt;With the combination of distributed tracing, Tracetest, and Cypress, true end-to-end tests that matches Martin Fowler’s definition, is finally achieved.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;An end-to-end test verifies that a system meets external requirements and achieves its goals, testing the entire system, from end to end.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With these tests in place, your entire dev team can release at high velocity with greater confidence.&lt;/p&gt;

&lt;p&gt;Want to see some examples of these Tracetest infused Cypress tests? We are running these tests in our demo environment. &lt;a href="https://app.tracetest.io/organizations/ttorg_2179a9cd8ba8dfa5/invites/invite_760904a64b4b9dc9/accept" rel="noopener noreferrer"&gt;Join the environment&lt;/a&gt; and look at the three Cypress tests:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1705666756%2FBlogposts%2Fcloud-native-observability-cypress-unlikely-marriage%2Ftestlist_zn8mxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1705666756%2FBlogposts%2Fcloud-native-observability-cypress-unlikely-marriage%2Ftestlist_zn8mxd.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1705666756/Blogposts/cloud-native-observability-cypress-unlikely-marriage/testlist_zn8mxd.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have questions? Join the discussion with the matchmakers of this union in the &lt;a href="https://dub.sh/tracetest-community" rel="noopener noreferrer"&gt;Tracetest Slack channel&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>observability</category>
      <category>testing</category>
      <category>cloudnative</category>
      <category>cypress</category>
    </item>
    <item>
      <title>Tracetest - Recapping 2023</title>
      <dc:creator>Ken Hamric</dc:creator>
      <pubDate>Thu, 11 Jan 2024 13:08:29 +0000</pubDate>
      <link>https://dev.to/kubeshop/tracetest-recapping-2023-4ei7</link>
      <guid>https://dev.to/kubeshop/tracetest-recapping-2023-4ei7</guid>
      <description>&lt;p&gt;What a year 2023 was for Tracetest and Trace-based Testing! Let's start by looking at it through numbers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grew from &lt;a href="https://star-history.com/#kubeshop/tracetest&amp;amp;Timeline" rel="noopener noreferrer"&gt;&amp;lt;400⭐ to 768⭐&lt;/a&gt;!&lt;/li&gt;
&lt;li&gt;Had &lt;a href="https://github.com/kubeshop/tracetest/tags" rel="noopener noreferrer"&gt;52 public releases&lt;/a&gt; - exactly one per week!&lt;/li&gt;
&lt;li&gt;Added integrations for &lt;a href="https://docs.tracetest.io/configuration/overview#supported-trace-data-stores" rel="noopener noreferrer"&gt;9 additional tracing backends&lt;/a&gt;: DataDog, AWS X-Ray, Honeycomb, Azure Apps Insight, SigNoz, Dynatrace, Lightstep, Elastic, and New Relic. This makes a total of 15 supported tracing backends, plus any others that use the OpenTelemetry Collector.&lt;/li&gt;
&lt;li&gt;Added &lt;a href="https://docs.tracetest.io/tools-and-integrations/overview" rel="noopener noreferrer"&gt;5 integrations&lt;/a&gt;: Github Actions, Tekton, Keptn, Testkube, and our favorite, k6. Expect many more of these in 2024!&lt;/li&gt;
&lt;li&gt;Attended 10 different conferences across 3 different continents, including KubeCon Amsterdam and Chicago, Monitorama in Portland, DeveloperWeek in both San Mateo and Latin America, OpenSearch in Seattle, FOSDEM in Brussels, and others.&lt;/li&gt;
&lt;li&gt;Published 3 user case studies: &lt;a href="https://tracetest.io/case-studies/how-sigma-software-built-load-testing-for-their-microservices-with-k6-tracetest" rel="noopener noreferrer"&gt;Sigma Software&lt;/a&gt; testing with k6+Tracetest, &lt;a href="https://tracetest.io/case-studies/how-uzufly-built-end-to-end-testing-serverless-web-app-with-distributed-traces" rel="noopener noreferrer"&gt;Uzufly&lt;/a&gt; testing from the browser with OpenTelemetry, and how &lt;a href="https://tyk.io/blog/how-tyk-leverages-tracetest-for-effective-integration-testing-of-opentelemetry/" rel="noopener noreferrer"&gt;Tyk is leveraging Tracetest&lt;/a&gt; for integration testing of their new native support of OpenTelemetry.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With all the activity, new users and use cases, releases, and improvements, it is hard to pick the most impactful, but four stand out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.tracetest.io/tools-and-integrations/k6/" rel="noopener noreferrer"&gt;k6 Integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tracetest.io/blog/tracetest-analyzer-identify-patterns-and-issues-with-code-instrumentation" rel="noopener noreferrer"&gt;Trace Analyzer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tracetest.io/blog/why-did-opentelemetry-ditch-black-box-tests" rel="noopener noreferrer"&gt;Inclusion in the OpenTelemetry Community Demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://app.tracetest.io/" rel="noopener noreferrer"&gt;Tracetest Managed Platform&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  k6 Integration
&lt;/h2&gt;

&lt;p&gt;In February, Tracetest teamed up with k6 to provide deep assertions when running load tests. When running a load test against any complex system, being able to detect where the system is failing and verify the entire flow is critical.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.tracetest.io/tools-and-integrations/k6/" rel="noopener noreferrer"&gt;The k6 integration&lt;/a&gt; allows trace-based tests to be run against each of the hundreds or thousands of runs in a load test, enabling deep detection across the full system.&lt;/p&gt;

&lt;p&gt;Check out this 8 minute video guide on how to get started!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=cv-9-pkLqbY" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=cv-9-pkLqbY&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Trace Analyzer
&lt;/h2&gt;

&lt;p&gt;In May, the team introduced the &lt;a href="https://tracetest.io/blog/tracetest-analyzer-identify-patterns-and-issues-with-code-instrumentation" rel="noopener noreferrer"&gt;Trace Analyzer&lt;/a&gt; as a means to help developers and teams instrument their applications easier and more consistently. We considered calling it the &lt;em&gt;Trace Linter.&lt;/em&gt; Its purpose is to inspect the trace data and ensure it is following the OpenTelemetry semantic conventions, look for common problems and maintain standards, and help you find security problems. These additional validations can be run automatically as part of your CI/CD process, allowing you to verify the quality of your instrumentation across all your teams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1704892868%2FBlogposts%2F2023-tracetest-product-recap%2FUntitled_14_qzbww4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1704892868%2FBlogposts%2F2023-tracetest-product-recap%2FUntitled_14_qzbww4.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1704892868/Blogposts/2023-tracetest-product-recap/Untitled_14_qzbww4.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inclusion in the OpenTelemetry Community Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://opentelemetry.io/" rel="noopener noreferrer"&gt;OpenTelemetry&lt;/a&gt; is a CNCF incubating project promoting an open standards-based approach to instrumenting applications to enable observability. It is 'the' standard in the observability space, with widespread industry support.&lt;/p&gt;

&lt;p&gt;The community behind OpenTelemetry provides an &lt;a href="https://opentelemetry.io/docs/demo/" rel="noopener noreferrer"&gt;OpenTelemetry Demo&lt;/a&gt; which allows new users to understand how to instrument their own systems. This demo is a microservice-based architecture, written in 11 different languages, with over 12 services, and maintained by dozens of contributors.&lt;/p&gt;

&lt;p&gt;In May of 2023, the community decided they needed better testing due to a number of breaking commits, and &lt;a href="https://tracetest.io/blog/why-did-opentelemetry-ditch-black-box-tests" rel="noopener noreferrer"&gt;Tracetest was able to contribute a series of trace-based tests&lt;/a&gt; to ensure the quality of the releases. These tests are now run as part of the CI/CD process for the demo, making Tracetest a key component in ensuring successful releases for the project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1704892916%2FBlogposts%2F2023-tracetest-product-recap%2FUntitled_15_wlqq9u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1704892916%2FBlogposts%2F2023-tracetest-product-recap%2FUntitled_15_wlqq9u.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1704892916/Blogposts/2023-tracetest-product-recap/Untitled_15_wlqq9u.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tracetest Managed Platform
&lt;/h2&gt;

&lt;p&gt;In October, the &lt;a href="https://tracetest.io/blog/opentelemetry-is-not-just-for-monitoring-and-troubleshooting-any-longer-announcing-tracetest-open-beta" rel="noopener noreferrer"&gt;Tracetest commercial offering&lt;/a&gt; was released, and the open-source version was rebranded as &lt;a href="https://github.com/kubeshop/tracetest" rel="noopener noreferrer"&gt;Tracetest Core&lt;/a&gt;. Tracetest introduced several new features in addition to the ones already available in Tracetest Core.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tracetest Core installs directly into the test environment. However, with ephemeral test instances, the results were not accessible once the tests were finished and the test instance was reclaimed. This resulted in the loss of one of the key benefits of trace-based testing - the ability to visually observe the entire process of a failed test run, including which assertions failed and what was happening in the system before and after the failure point.&lt;/li&gt;
&lt;li&gt;Tracetest has a loyal following of customers using Tracetest to test FaaS (Function-as-a-Service) based systems. These customers do not want to manage servers, and the hosted Tracetest eliminates this unwanted additional work.&lt;/li&gt;
&lt;li&gt;Tracetest eases both networking and installation. Tracetest Core requires a local server installation into Docker or Kubernetes. This made local development on the desktop harder, as network configuration was required. With Tracetest, you just install an agent on your local machine, in Docker, or in Kubernetes, and it immediately can listen for OpenTelemetry spans.&lt;/li&gt;
&lt;li&gt;Tracetest Core is built for a single user and single environment. Tracetest enables organizations, with multiple environments, users, roles, and SSO.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Looking Forward
&lt;/h2&gt;

&lt;p&gt;The team is excited to enter 2024! We will expand the scope of Tracetest by integrating it into the load test, synthetic monitoring, and front-end testing fields. Our first major announcement will be the introduction of true end-to-end testing using Trace-Based Testing (hint: with Cypress). Stay tuned for this thrilling and potentially groundbreaking release!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1704892936%2FBlogposts%2F2023-tracetest-product-recap%2Fimage_62_zbwink.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fdjwdcmwdz%2Fimage%2Fupload%2Fv1704892936%2FBlogposts%2F2023-tracetest-product-recap%2Fimage_62_zbwink.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1704892936/Blogposts/2023-tracetest-product-recap/image_62_zbwink.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would you like to learn more about Tracetest and what it brings to the table? Visit the Tracetest &lt;a href="https://docs.tracetest.io/getting-started/installation" rel="noopener noreferrer"&gt;docs&lt;/a&gt; and try it out by &lt;a href="https://tracetest.io/download" rel="noopener noreferrer"&gt;downloading&lt;/a&gt; it today!&lt;/p&gt;

&lt;p&gt;Also, please feel free to join our &lt;a href="https://dub.sh/tracetest-community" rel="noopener noreferrer"&gt;Slack community&lt;/a&gt;, give &lt;a href="https://github.com/kubeshop/tracetest" rel="noopener noreferrer"&gt;Tracetest a star on GitHub&lt;/a&gt;, or schedule a &lt;a href="https://calendly.com/ken-kubeshop/45min" rel="noopener noreferrer"&gt;time to chat 1:1&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>observability</category>
      <category>testing</category>
      <category>development</category>
    </item>
    <item>
      <title>👨‍🚀 Tracetest Monthly Newsletter - November 2023</title>
      <dc:creator>Ken Hamric</dc:creator>
      <pubDate>Mon, 11 Dec 2023 02:14:57 +0000</pubDate>
      <link>https://dev.to/kubeshop/tracetest-monthly-newsletter-november-2023-7j0</link>
      <guid>https://dev.to/kubeshop/tracetest-monthly-newsletter-november-2023-7j0</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;a href="https://discord.gg/8MtcMrQNbX"&gt;Join the Community Discord here&lt;/a&gt; to talk all things Tracetest, get instant support from our team, or simply say hi! If you like what we're doing, and haven't already, &lt;a href="https://github.com/kubeshop/tracetest"&gt;leave us a ⭐ on GitHub&lt;/a&gt;. Thank you for being part of the community. Your support and feedback are invaluable! ❤️&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hello, Tracetest Community! 👋&lt;/p&gt;

&lt;p&gt;We are thrilled to share the latest updates and exciting news from the Tracetest community! Take a look at what's happened in the last month. 👇&lt;/p&gt;

&lt;h2&gt;
  
  
  Hot tip of the day!
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Parent-child Relation and :First Filtering
&lt;/h3&gt;

&lt;p&gt;There are times when a span you want to select appears several times in a trace, but you want to test a specific instance of it. To select the particular span, you can specify its parent or its position. For example, when trying to test the FeatureFlagService GetFlag operation, we see it matches 3 spans, but we want to apply an assertion against the one called by the get_product_list operation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mTpdZEie--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455661/newsletters/november%25202023/select_spans_b4_oklspu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mTpdZEie--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455661/newsletters/november%25202023/select_spans_b4_oklspu.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455661/newsletters/november%202023/select_spans_b4_oklspu.png" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1QhvMqqo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455737/newsletters/november%25202023/trace_b4_bmyozg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1QhvMqqo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455737/newsletters/november%25202023/trace_b4_bmyozg.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455737/newsletters/november%202023/trace_b4_bmyozg.png" width="800" height="799"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using the information from the &lt;a href="https://docs.tracetest.io/concepts/selectors"&gt;selectors docs&lt;/a&gt;, we can see how to select the first span that is a child of the ‘get_product_list’.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R98xyIOZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455816/newsletters/november%25202023/select_spans_after_snlywv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R98xyIOZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455816/newsletters/november%25202023/select_spans_after_snlywv.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455816/newsletters/november%202023/select_spans_after_snlywv.png" width="800" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OoKYE6XN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455870/newsletters/november%25202023/trace_after_zmhyb1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OoKYE6XN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455870/newsletters/november%25202023/trace_after_zmhyb1.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455870/newsletters/november%202023/trace_after_zmhyb1.png" width="574" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can then create &lt;strong&gt;add&lt;/strong&gt; assertions that apply to the specific span, verifying the value retrieved from the feature flag service by get_product_list is correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What's New with Tracetest&lt;/strong&gt; 🎉
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Tracetest Core&lt;/strong&gt; &lt;a href="https://github.com/kubeshop/tracetest/releases/tag/v0.14.7"&gt;v0.14.7&lt;/a&gt; &lt;strong&gt;has been released:&lt;/strong&gt; This update includes a brand new, lovely, test creation flow, skip trace capability, and more. Lots and lots of new capability released... we will cover the highlights below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;New! ‘skip trace’ allows black box tests!&lt;/strong&gt; You can now run Tracetest on code bases you have not instrumented… yet. Run a black box test, instrument with OpenTelemetry, and then upgrade to a full end to end test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CiXcFC8O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455923/newsletters/november%25202023/skip-trace_ayjps9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CiXcFC8O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455923/newsletters/november%25202023/skip-trace_ayjps9.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455923/newsletters/november%202023/skip-trace_ayjps9.png" width="654" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try our demos!&lt;/strong&gt; We made it easy to try Tracetest, as well as play around with its features to learn more about our OpenTelemetry solution. We have added the &lt;a href="https://app.tracetest.io/organizations/ttorg_2179a9cd8ba8dfa5/invites/invite_646747b36e9ee487/accept"&gt;OpenTelemetry Community Demo&lt;/a&gt;, an Astronomy Store, and our own &lt;a href="https://app.tracetest.io/organizations/ttorg_2179a9cd8ba8dfa5/invites/invite_760904a64b4b9dc9/accept"&gt;Pokeshop API demo&lt;/a&gt;. &lt;a href="https://docs.tracetest.io/getting-started/try-live-demos"&gt;Check out the docs&lt;/a&gt; and use the ‘join’ links for each demo to immediately run and create tests. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Invite Links.&lt;/strong&gt; Aren’t these links to join the tracetest-demo organization and be registered as an engineer for the demo environments cool? Creating these &lt;a href="https://docs.tracetest.io/concepts/roles-and-permissions#adding-organization-members-by-invite-link"&gt;magic invite links&lt;/a&gt; is part of the product now! Slack an invite to allow people to join a particular Org / environment with a particular role.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run Agent on the Cloud (BETA).&lt;/strong&gt; A Tracetest customer asked if they could use &lt;a href="http://app.tracetest.io"&gt;app.tracetest.io&lt;/a&gt; without running an agent locally? They have a large function as a service (FaaS) based system with lots of complexity, and want to use Tracetest to build tests. They have public endpoints, and wanted to send the trace data to tracetest.io via the OTel collector, having Tracetest run the agent. It is &lt;a href="https://docs.tracetest.io/concepts/cloud-agent"&gt;now in Beta&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Integrations&lt;/strong&gt; 🤝
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;New Github Action!&lt;/strong&gt; Making it easy to connect to &lt;a href="http://Tracetest.io"&gt;Tracetest.io&lt;/a&gt; from Github Action Workflows. &lt;a href="https://github.com/kubeshop/tracetest-agent-action"&gt;Try it!&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test Kafka Based Architectures!&lt;/strong&gt; Our own Daniel Dias &lt;a href="https://github.com/kubeshop/tracetest/tree/main/examples/tracetesting-event-driven-systems"&gt;created an example&lt;/a&gt; and wrote a technical blog post documenting how to &lt;a href="https://tracetest.io/blog/testing-event-driven-systems-with-opentelemetry"&gt;test event-driven systems with OpenTelemetry&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bcLQHeP9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455991/newsletters/november%25202023/test-event-based-kafka-system_a2dkq3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bcLQHeP9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455991/newsletters/november%25202023/test-event-based-kafka-system_a2dkq3.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1701455991/newsletters/november%202023/test-event-based-kafka-system_a2dkq3.png" width="800" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;From the Community 🎙️&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tracetest was at KubeCon NA!&lt;/strong&gt; Jorge and I attended OTel Day on Monday and talked to people at the Tracetest booth Tuesday through Thursday. 100+ great conversations with current and future users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IugDyU6---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701456034/newsletters/november%25202023/kubecon_xnrsrf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IugDyU6---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701456034/newsletters/november%25202023/kubecon_xnrsrf.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1701456034/newsletters/november%202023/kubecon_xnrsrf.png" width="676" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Didn’t Make it to Kubecon?&lt;/strong&gt; Read about what we saw in our ‘&lt;a href="https://tracetest.io/blog/observability-at-kubecon-north-america-2023-in-chicago"&gt;Observability at KubeCon&lt;/a&gt;’ article.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3nMbYvDF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701456087/newsletters/november%25202023/opentelemetry-day_ztzz0t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3nMbYvDF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701456087/newsletters/november%25202023/opentelemetry-day_ztzz0t.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1701456087/newsletters/november%202023/opentelemetry-day_ztzz0t.png" width="454" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;KCD Austria Talk.&lt;/strong&gt; Adnan Radic’s conference talk, &lt;a href="https://www.youtube.com/watch?v=ih7S-HXdo_Y"&gt;Distributed tracing is awesome, testing is not… until now&lt;/a&gt;, has been published on Youtube. Watch it!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tracetest is part of the OTel Demo CI/CD Pipeline!&lt;/strong&gt; Austin Parker, one of the co-founders and maintainers of OpenTelemetry, &lt;a href="https://github.com/open-telemetry/opentelemetry-demo/pull/1278"&gt;just added&lt;/a&gt; Tracetest tests to the CI/CD process for the official &lt;a href="https://opentelemetry.io/docs/demo/"&gt;OTel Demo&lt;/a&gt;. Our team wrote &lt;a href="https://github.com/open-telemetry/opentelemetry-demo/tree/main/test/tracetesting"&gt;these tests&lt;/a&gt; earlier this summer to help maintain quality of this important Open Source project, but they were run manually… until now! It is now &lt;a href="https://github.com/open-telemetry/opentelemetry-demo/actions/runs/7030276512/job/19129604046#step:4:16405"&gt;automated as part of the build system&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5ApuyTVt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701456144/newsletters/november%25202023/OpenTelemetry_Demo_Merge_nwlphg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5ApuyTVt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701456144/newsletters/november%25202023/OpenTelemetry_Demo_Merge_nwlphg.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1701456144/newsletters/november%202023/OpenTelemetry_Demo_Merge_nwlphg.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contribute to the &lt;a href="https://github.com/open-telemetry/opentelemetry-demo"&gt;OpenTelemetry Community Demo&lt;/a&gt;! Our very own Adnan Rahic contributed to the OTel Demo, then wrote an article teaching others how. Read: &lt;a href="https://tracetest.io/blog/the-power-of-traces-learn-by-contributing-to-opentelemetry"&gt;The Power of Traces: Learn by Contributing to OpenTelemetry&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Like what we do?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do you have a specific use case you would like us to cover? Do you want to contribute to Tracetest?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At Tracetest, we welcome all contributions!&lt;/p&gt;

&lt;p&gt;Not sure where to start? You can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visit our &lt;a href="https://tracetest.io/community"&gt;Community Page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Check out our contributing guidelines &lt;a href="https://github.com/kubeshop/tracetest/blob/main/CONTRIBUTING.md"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://calendly.com/ken-kubeshop/45min?month=2023-08"&gt;Book a meeting&lt;/a&gt; with us or chat with our team on &lt;a href="https://discord.gg/8MtcMrQNbX"&gt;Discord&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you for being a part of the Tracetest community! We are committed to providing the necessary tools, knowledge, and resources to succeed in the field of tracing and testing. Let’s stay in touch and continue exploring. Stay tuned for more exciting updates in the coming months.&lt;/p&gt;

&lt;p&gt;Super long recap, but we got a ton done in November! See you next month!&lt;/p&gt;

&lt;p&gt;p.s. Adnan is out this week, but he has a great reason! Congratulations Adnan!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CPcSqR7N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701456196/newsletters/november%25202023/Adnan-married_ka4sek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CPcSqR7N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1701456196/newsletters/november%25202023/Adnan-married_ka4sek.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1701456196/newsletters/november%202023/Adnan-married_ka4sek.png" width="506" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>observability</category>
      <category>cloudnative</category>
      <category>opentelemetry</category>
    </item>
    <item>
      <title>OpenTelemetry is not just for Monitoring and Troubleshooting any longer. Announcing Tracetest Open Beta!</title>
      <dc:creator>Ken Hamric</dc:creator>
      <pubDate>Thu, 05 Oct 2023 18:54:43 +0000</pubDate>
      <link>https://dev.to/kubeshop/opentelemetry-is-not-just-for-monitoring-and-troubleshooting-any-longer-announcing-tracetest-open-beta-1ab1</link>
      <guid>https://dev.to/kubeshop/opentelemetry-is-not-just-for-monitoring-and-troubleshooting-any-longer-announcing-tracetest-open-beta-1ab1</guid>
      <description>&lt;p&gt;We are excited to announce the Open Beta launch of Tracetest, the best way to develop and test with OpenTelemetry!&lt;/p&gt;

&lt;p&gt;With this tool, we enable a concept that, up to now, has merely been an industry buzzword - &lt;a href="https://tracetest.io/blog/the-difference-between-tdd-and-odd"&gt;Observability-Driven Development (ODD)&lt;/a&gt;. The promise of observability-driven development is that Observability will be “baked in” from the beginning of the development process, not just bolted on at the end to satisfy the need for visibility in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  How will this shift occur?
&lt;/h2&gt;

&lt;p&gt;Ted Young, co-founder of the &lt;a href="https://opentelemetry.io/"&gt;OpenTelemetry project&lt;/a&gt;, told me in a recent conversation:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“In general, I would like to see more tools that are focused on development and instrumentation, not production.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Currently, most Observability tools are focused on one thing - Production. Without tooling that enables developers to seamlessly instrument code, maintain consistency, and write tests to verify functionality, Observability remains primarily a solution geared towards operations. This limits its potential to deliver value to other parts of the organization.&lt;/p&gt;

&lt;h2&gt;
  
  
  How will Tracetest fill the gap?
&lt;/h2&gt;

&lt;p&gt;Tracetest is already &lt;a href="https://opentelemetry.io/blog/2023/testing-otel-demo/"&gt;the leading trace-based testing solution on the market today, and part of the OpenTelemetry Demo repo&lt;/a&gt;. It uses the power of distributed tracing, offering comprehensive insights into the inner workings of your code during testing. When you can observe what your code is doing and the interaction between services, writing tests becomes a trivial process.&lt;/p&gt;

&lt;p&gt;Tracetest achieves this by providing a comprehensive service map of your system under test. In essence, Tracetest leverages distributed traces, allowing users to construct tests based on these traces. This enables the creation of specific criteria and assertions tailored to each unique end-to-end flow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5FuOTWLH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1688476657/docs/screely-1688476653521_omxe4r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5FuOTWLH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1688476657/docs/screely-1688476653521_omxe4r.png" alt="assertions" width="800" height="560"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image 1: Tracetest Assertions based on Distributed Traces&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Adoptees see the time required for writing integration or end-to-end tests across their Cloud Native systems drop from hours to minutes. It is platform agnostic, working with all the major observability vendors such as Datadog, New Relic, Honeycomb, Dynatrace, &lt;a href="https://tracetest.io/integrations"&gt;and 10 others&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ui5R0bR0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1696330847/Blogposts/announcing-tracetest-beta/Screenshot_2023-10-03_at_12.59.21_f6dgw1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ui5R0bR0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1696330847/Blogposts/announcing-tracetest-beta/Screenshot_2023-10-03_at_12.59.21_f6dgw1.png" alt="tracetest integrations" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image 2: Tracetest Data Store Integrations&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Additionally, the individual developer experience surrounding instrumentation of your code is vastly improved with a newly introduced (and &lt;a href="https://tracetest.io/pricing"&gt;free&lt;/a&gt;) “localMode”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--31Plvo3R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1696417290/docs/screely-1696253224366_f62411_1_evtc9u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--31Plvo3R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1696417290/docs/screely-1696253224366_f62411_1_evtc9u.png" alt="localmode" width="800" height="279"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image 3: Tracetest localMode&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With localMode, developers can run a simple agent in their console, Docker, or Kubernetes workspace and immediately begin seeing and improving their instrumentation.&lt;/p&gt;

&lt;p&gt;Tracetest will also let you know if you are not following the &lt;a href="https://opentelemetry.io/docs/concepts/semantic-conventions/"&gt;OpenTelemetry semantic conventions&lt;/a&gt;, and you can use the &lt;a href="https://docs.tracetest.io/analyzer/concepts"&gt;Analyzer&lt;/a&gt; to enforce the &lt;a href="https://opentelemetry.io/docs/specs/otel/"&gt;OpenTelemetry specification standards&lt;/a&gt; across your dev teams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QRkxfnNk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1688476460/docs/screely-1688476455986_q24aa2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QRkxfnNk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1688476460/docs/screely-1688476455986_q24aa2.png" alt="analyzer" width="800" height="560"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image 4: Tracetest Analyzer&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Key Features of Tracetest Core
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/kubeshop/tracetest"&gt;open-source version&lt;/a&gt; of Tracetest, which we are referring to as Tracetest Core, has had a warm reception, generating excitement across the industry and garnering over 700 stars in its first 18 months.&lt;/p&gt;

&lt;p&gt;Tracetest Core offers a unique feature that makes building integration tests much faster. By using Distributed Tracing, it reduces the required time by 98%.&lt;/p&gt;

&lt;p&gt;Here's how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Trigger:&lt;/strong&gt; Use tailored test triggers, like API calls (HTTP or gRPC) or Kafka streams, to get system responses and initiate tracing. Tracetest Core automatically adds essential headers to these requests for comprehensive tracing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trace:&lt;/strong&gt; Tracetest Core uses a polling algorithm to query the existing tracing solution and gather a complete trace for analysis. The trace is shown in both a timeline and system view.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test:&lt;/strong&gt; Based on response and trace data, developers can create customized assertions. These assertions can check status codes, business data, span existence, anticipated flow, and more. For example, you can validate that all database calls complete within a specific time frame.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automate:&lt;/strong&gt; Tracetest Core can run in your CI/CD pipelines.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With Tracetest Core, creating integration tests is no longer a time-consuming task. Instead of taking days, you can now build comprehensive integration and end-to-end tests within minutes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Create a SaaS Version of Tracetest?
&lt;/h2&gt;

&lt;p&gt;Our users did point out some limitations with Tracetest Core.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It’s Heavy.&lt;/strong&gt; Not super heavy, mind you, but it needs several parts and pieces to run - the core executable, Postgres, etc. Due to this, the install took a few minutes and was limited to Docker and Kubernetes environments. It’s not the “grab it and go” test tool we think it can be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Networking is Hard.&lt;/strong&gt; We are not all Cisco certified engineers or experts in Docker networking. Not being able to collect trace information directly from the environment you are working in made getting started with Tracetest harder than desired and lead to more support needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server Installation is Not Ephemeral-friendly&lt;/strong&gt;. GitHub Actions or other CI/CD environments you spin up, and then spin down, as part of the test environment resulted in a use pattern we did not expect - the installation of Tracetest server into a transient environment. Spin up Tracetest, run tests, shut it down. This eliminates one of the most valuable capabilities of Tracetest - seeing your trace-based test results via the UI. By viewing a failed test in the UI, you can see not just failed assertions, but also look at the system surrounding it using the full captured trace. It also allows you to adjust your assertions at that point and resave your test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kyYnYhMI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1696360615/Blogposts/announcing-tracetest-beta/unnamed_22_1_pbzhsc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kyYnYhMI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1696360615/Blogposts/announcing-tracetest-beta/unnamed_22_1_pbzhsc.png" alt="test specs" width="800" height="287"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image 5: Tracetest Test Specs&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monetization.&lt;/strong&gt; We are a small, dedicated team working full time on Tracetest. We draw salaries, have house notes to pay, and have children and pets to feed. Putting Tracetest on a path to sustainability is critical to the success of continuing to develop Tracetest Core. There… we said the quiet part out loud.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bfal81FR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1696360670/Blogposts/announcing-tracetest-beta/unnamed_puqsuw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bfal81FR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1696360670/Blogposts/announcing-tracetest-beta/unnamed_puqsuw.jpg" alt="scout" width="800" height="645"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image 6: Tracetest’s Chief Happiness Officer Scout likes treats&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Use Tracetest SaaS instead of Tracetest Core
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Managed infrastructure.&lt;/strong&gt; Tracetest runs in the cloud (available for on-prem deployments as well), where you have a central location for storing, viewing and running tests. No need to manage your own Tracetest Core instance. It’s a clear benefit for distributed systems, serverless, and microservice architectures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It is super lightweight.&lt;/strong&gt; With Tracetest you install a lightweight agent in your working environment, whether it's on your local machine, Docker, Kubernetes, Github Actions, or similar platforms.&lt;/p&gt;

&lt;p&gt;This agent has two jobs when a test is run:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Trigger your local code via REST, gRPC, or Kafka.&lt;/li&gt;
&lt;li&gt;Collect the distributed trace either directly or by reaching out to your observability solution.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;It has a super easy install.&lt;/strong&gt; For MacOS, there are just two commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;brew install kubeshop/tracetest/tracetest&lt;/span&gt;
&lt;span class="s"&gt;tracetest start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Click &lt;a href="https://docs.tracetest.io/getting-started/installation"&gt;here&lt;/a&gt; to view installation instructions for other operating systems.&lt;/p&gt;

&lt;p&gt;You can start visualizing traces and creating tests right away, whether it's ad hoc tests for code in development or complete integration tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Networking is Easy (Really!)&lt;/strong&gt; Since you install the agent directly into the environment where you are running your application, there is no complex networking. When developing in localMode, the agent listens on the common &lt;a href="https://github.com/open-telemetry/opentelemetry-proto/blob/main/docs/specification.md"&gt;OpenTelemetry Line Protocol (OTLP)&lt;/a&gt; on ports 4317 &amp;amp; 4318 automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tracetest is persistent, not ephemeral!&lt;/strong&gt; You can work and run tests in ephemeral environments such as GitHub Actions using the Tracetest Agent, which sends test results to Tracetest. These results will be available for you to examine the full trace, diagnose the issue, or share with the team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It is Free!&lt;/strong&gt; Tracetest will be the easiest, most convenient tool to instrument and test your application. As a developer, you can launch the Tracetest Agent in the free localMode and immediately begin visualizing the trace, improving the quality of your instrumentation, and building tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I thought you needed $$$ to feed your dog?&lt;/strong&gt; Eventually, you will want to run these tests in automated CI/CD pipelines, create a shared environment, configure the data store you are using for traces, and run the tests. These shared environments for automated testing will eventually be part of a paid plan. You can collect data from OTLP or connect to a wide range of observability backends, such as Grafana Tempo, OpenSearch, CloudWatch, and more. For the Beta period, these shared environments are also free as we seek feedback and input to improve Tracetest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it! Give us feedback!
&lt;/h2&gt;

&lt;p&gt;We are looking for feedback. Go to &lt;a href="https://tracetest.io/"&gt;Tracetest.io&lt;/a&gt; and click “Get Started”. If you have questions, you can talk to us on the &lt;a href="https://discord.com/channels/884464549347074049/1145765810242064475"&gt;Discord channel&lt;/a&gt;. You can also reach out to me on &lt;a href="https://www.linkedin.com/in/ken-hamric-016b1420/"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cloudnative</category>
      <category>testing</category>
      <category>distributedsystems</category>
      <category>development</category>
    </item>
    <item>
      <title>Why did OpenTelemetry Ditch Black-box Tests?</title>
      <dc:creator>Ken Hamric</dc:creator>
      <pubDate>Fri, 25 Aug 2023 19:19:58 +0000</pubDate>
      <link>https://dev.to/kubeshop/why-did-opentelemetry-ditch-black-box-tests-5ci4</link>
      <guid>https://dev.to/kubeshop/why-did-opentelemetry-ditch-black-box-tests-5ci4</guid>
      <description>&lt;p&gt;Black-box testing has long been the recommended technique for testing back-end architectures. This tendency to rely on them has continued even as major architectural and technology shifts have occurred.&lt;/p&gt;

&lt;p&gt;What are those shifts?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monolith to distributed, microservice-based systems&lt;/li&gt;
&lt;li&gt;Logs to distributed logging to distributed tracing&lt;/li&gt;
&lt;li&gt;Synchronous, blocking based APIs to asynchronous handling of requests&lt;/li&gt;
&lt;li&gt;Database centric design to message based architectures&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Are black-box tests still adequate?
&lt;/h2&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;This summer, the &lt;a href="https://github.com/open-telemetry/opentelemetry-demo"&gt;OpenTelemetry (OTel) Demo&lt;/a&gt; (see below) experienced growing pains due to the rapid pace of merged PRs by numerous contributors. This resulted in releases with broken features and lower than desired quality. It was occurring in spite of test coverage with a suite of black box tests having been in place for quite some time.&lt;/p&gt;

&lt;p&gt;This article will look at how trace-based testing techniques, which in turn rely on modern observability techniques, were used to increase the reliability and confidence in releases. The lessons learned can also help you.&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenTelemetry CNCF Project (OTel)
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://opentelemetry.io/"&gt;OpenTelemetry Project&lt;/a&gt;, commonly referred to as OTel for short, was formed in 2019 when &lt;a href="https://tracetest.io/blog/tracing-the-history-of-distributed-tracing-opentelemetry"&gt;OpenCensus and OpenTracing merged&lt;/a&gt;. The goal was to provide one unified standard to collect observability data. Before this standard, developers implementing observability were forced to choose a particular vendor's application performance monitoring (APM) solution and instrument their application with vendor specific tooling. This led to vendor lock-in.&lt;/p&gt;

&lt;p&gt;From the observability vendor perspective, maintaining instrumentation across the wide spectrum of languages and technologies was a daunting task, even for the larger vendors. By moving to an open standard with OTel, developers have a standard way to instrument their code and vendors can focus on how to visualize and analyze the data.&lt;/p&gt;

&lt;p&gt;OpenTelemetry focuses on 3 major observability signals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logs&lt;/li&gt;
&lt;li&gt;Metrics&lt;/li&gt;
&lt;li&gt;Distributed Traces&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of these, distributed tracing is considered the most valuable and was the starting point for the &lt;a href="https://opentelemetry.io/docs/what-is-opentelemetry/"&gt;OpenTelemetry Project&lt;/a&gt;. A distributed trace records the paths taken by requests as they propagate through multi-service architectures, showing you both call order, timing, and containing the details of each step.&lt;/p&gt;

&lt;p&gt;A distributed trace has four components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the trace&lt;/li&gt;
&lt;li&gt;spans representing each step&lt;/li&gt;
&lt;li&gt;attributes associated to each span&lt;/li&gt;
&lt;li&gt;events associated to each span&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below is a typical trace:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ti9ag4Xf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692648787/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/trace_sqosxm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ti9ag4Xf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692648787/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/trace_sqosxm.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1692648787/Blogposts/Black%20box%20testing%20against%20OpenTelemetry%20Demo/trace_sqosxm.png" width="800" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  OpenTelemetry Demo Microservice App
&lt;/h2&gt;

&lt;p&gt;In April of 2021, the OpenTelemetry Project decided to create a demo application to showcase how to instrument a heterogeneous distributed application. You can install and run the OpenTelemetry Demo in Docker &lt;a href="https://docs.tracetest.io/live-examples/opentelemetry-store/overview/#get-and-run-the-demo"&gt;with these commands&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/open-telemetry/opentelemetry-demo.git
&lt;span class="nb"&gt;cd &lt;/span&gt;opentelemetry-demo/
docker compose up &lt;span class="nt"&gt;--no-build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;💡 Note: If you're running on Apple Silicon, run &lt;code&gt;docker compose build&lt;/code&gt; in order to create local images vs. pulling them from the repository.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The application, in keeping with the observability theme of the OTel project, is an Astronomy Store Front. This application has evolved to have &lt;a href="https://opentelemetry.io/docs/demo/#language-feature-reference"&gt;11 different languages and 12 major services&lt;/a&gt;, and it demonstrates both automatic and manual instrumentation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H0xAWfC6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692650967/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/languages-and-services-used-in-OTel-Demo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H0xAWfC6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692650967/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/languages-and-services-used-in-OTel-Demo.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1692650967/Blogposts/Black%20box%20testing%20against%20OpenTelemetry%20Demo/languages-and-services-used-in-OTel-Demo.png" width="678" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The application is used by developers beginning to learn observability, enterprises adopting OTel that want to be able to examine a working application, and by vendors that want to demonstrate their observability related product working with a complex application. The &lt;a href="https://github.com/open-telemetry/opentelemetry-demo#demos-featuring-the-astronomy-shop"&gt;list of companies&lt;/a&gt; that work with and rely on the demo is extensive:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cx2475oY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692651228/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/vendors-utilizing-opentelemetry-demo_cskadg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cx2475oY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692651228/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/vendors-utilizing-opentelemetry-demo_cskadg.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1692651228/Blogposts/Black%20box%20testing%20against%20OpenTelemetry%20Demo/vendors-utilizing-opentelemetry-demo_cskadg.png" width="610" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project is quite popular, with over 1K stars on &lt;a href="https://github.com/open-telemetry/opentelemetry-demo"&gt;GitHub&lt;/a&gt; and over 500 forks. It has had 86 unique contributors, and the pace of change is rapid. In just the past month, 10 different open source contributors have merged 43 PRs into the repo. These developers work for different companies, are located all over the world, and are submitting changes to different areas of the application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5ccDmu1C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692651383/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/Commits-and-contributors-opentelemetry_jtp7px.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5ccDmu1C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692651383/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/Commits-and-contributors-opentelemetry_jtp7px.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1692651383/Blogposts/Black%20box%20testing%20against%20OpenTelemetry%20Demo/Commits-and-contributors-opentelemetry_jtp7px.png" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s add all of this up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;11 different languages&lt;/li&gt;
&lt;li&gt;12 major services&lt;/li&gt;
&lt;li&gt;Both automatic and manual instrumentation&lt;/li&gt;
&lt;li&gt;10 different developers around the globe merging 43 PRs in the last month&lt;/li&gt;
&lt;li&gt;Numerous technologies including Kafka, Redis, Postgres, gRPC, HTTP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is considerable complexity, but not unlike most modern development environments which often have teams located in multiple areas, utilizing several development languages, a wide selection of technologies, and are committing code rapidly across numerous services. With this complexity, the risk of introducing errors when releasing is high.&lt;/p&gt;

&lt;p&gt;What technique is widely used to reduce risk and increase confidence when releasing code&lt;/p&gt;

&lt;p&gt;Tests!&lt;/p&gt;

&lt;h2&gt;
  
  
  Existing OpenTelemetry Demo Tests
&lt;/h2&gt;

&lt;p&gt;The OpenTelemetry Demo has had &lt;a href="https://opentelemetry.io/docs/demo/tests/"&gt;test coverage&lt;/a&gt; for quite some time. The front end is covered with tests created in Cypress which were written when the front end was migrated to NextJS in August of 2022. These tests can be run with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose run frontendTests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The back end was covered by black box tests against the gRPC endpoints that were written in AVA, a popular Node.js-based testing framework. They were added in July of 2022 with coverage across 9 of the services. These are straightforward black box tests, exercising a gRPC endpoint and verifying that the returned results were valid. Here is one of the AVA tests that verifies the checkout service, making sure the response to the call returns the proper data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;checkoutClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;oteldemo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CheckoutService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;CHECKOUT_SERVICE_ADDR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;grpc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createInsecure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;checkoutOrder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;checkoutClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;placeOrder&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;checkoutClient&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// --------------- Checkout Service ---------------&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkout: place order&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;checkoutOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;truthy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;truthy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shippingTrackingId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;truthy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shippingAddress&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shippingCost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currencyCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;USD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These existing AVA tests can be run with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose run integrationTests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Front-end tests, back-end black box tests. &lt;strong&gt;The world is great, and there are no problems!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Trouble in Testing the Distributed Application
&lt;/h2&gt;

&lt;p&gt;Except there were problems. Changes were breaking the demo, resulting in many issues utilizing the demo application for both new and established users. The issue was highlighted in a thread in the &lt;a href="https://cloud-native.slack.com/archives/C03B4CWV4DA"&gt;otel-community-demo&lt;/a&gt; channel of the &lt;a href="http://cloud-native.slack.com/"&gt;CNCF Slack&lt;/a&gt; posted in May of 2023. This thread was started by one of the lead contributors to the repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Kuv1Znj3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692651825/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/Trouble-Testing-Distributed-App_slbjqz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Kuv1Znj3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692651825/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/Trouble-Testing-Distributed-App_slbjqz.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1692651825/Blogposts/Black%20box%20testing%20against%20OpenTelemetry%20Demo/Trouble-Testing-Distributed-App_slbjqz.png" width="800" height="873"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There was enough complexity in the Demo application that unintended consequences were occurring, reducing confidence when deploying changes or adding new features. Looking at how the &lt;a href="https://opentelemetry.io/docs/demo/architecture/"&gt;architecture of the application&lt;/a&gt; had grown and the number of services involved, this is understandable:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9MIlPjDA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692884438/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/Screenshot_2023-08-24_at_15.37.56_hqsamu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9MIlPjDA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692884438/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/Screenshot_2023-08-24_at_15.37.56_hqsamu.png" alt="otel demo architecture" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What was needed was true end-to-end tests that could verify not only the response data from gRPC calls to the application, but could also verify that the entire application was working properly at a deeper level. Enter trace-based testing and Tracetest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trace-based Testing
&lt;/h2&gt;

&lt;p&gt;Traditionally, creating end-to-end tests that go past simple black box testing require instrumenting your application so you have visibility to deeper interactions throughout the system. When looking at these types of tests, typically 90% of the code enables visibility across the various services and technologies, while only 10% of the code in the test actually defines the triggering action or assertions.&lt;/p&gt;

&lt;p&gt;Trace-based testing is a technique that uses the instrumentation you have already enabled by making your code observable and allowing assertions to be created against data contained in it. It leverages the work your development team has already invested in instrumenting your application for observability. In doing so, trace-based testing dramatically reduces the effort and time involved in creating end-to-end tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tracetest
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://tracetest.io/"&gt;Tracetest&lt;/a&gt; is an &lt;a href="https://github.com/kubeshop/tracetest"&gt;open-source tool&lt;/a&gt; which enables trace-based testing. Read more about &lt;a href="https://tracetest.io/blog/introducing-tracetest-trace-based-testing-with-opentelemetry"&gt;Tracetest’s launch, here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Tests can be created in both the web-based user interface and via a code editor in a YAML format. Tracetest works with any &lt;a href="https://tracetest.io/integrations"&gt;OTel compatible vendor or open source solution&lt;/a&gt;, including Jaeger, Grafana Tempo, Dynatrace, Datadog, NewRelic, etc. The Tracetest server can be installed in Docker or Kubernetes, and you will also be able to use it without a server via the upcoming cloud version.&lt;/p&gt;

&lt;p&gt;The Tracetest team had previously contributed to the OpenTelemetry Community Demo in July of 2022 by &lt;a href="https://github.com/open-telemetry/opentelemetry-demo/pull/236"&gt;porting the Go-based front end to Next.js&lt;/a&gt;, so was familiar with contributing to the project and happy to help the community by adding a complete suite of true end-to-end tests against the back-end services.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trace-based Testing Suite
&lt;/h2&gt;

&lt;p&gt;The new tests were created in early July on a service by service basis and can be viewed in the &lt;a href="https://github.com/open-telemetry/opentelemetry-demo/tree/main/test/tracetesting"&gt;OpenTelemetry Demo repo, here&lt;/a&gt;. You can run the tests with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose run traceBasedTests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this article, we are going to look at the &lt;a href="https://github.com/open-telemetry/opentelemetry-demo/tree/main/test/tracetesting/frontend-service"&gt;frontend-service tests&lt;/a&gt; which focus on the checkout process. These tests are run as a test suite, and go all the way from checking the recommendation service to adding a product to a cart and then checking out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C0EXo2fc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692652287/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/Test-Suite-Checkout-Process_hvxmzk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C0EXo2fc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692652287/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/Test-Suite-Checkout-Process_hvxmzk.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1692652287/Blogposts/Black%20box%20testing%20against%20OpenTelemetry%20Demo/Test-Suite-Checkout-Process_hvxmzk.png" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking at the last test, &lt;em&gt;“Frontend: Checking out shopping cart”&lt;/em&gt;, we can see the structure of a Tracetest test. It is divided into two parts, the trigger and the test specs. The trigger, shown below, defines how the trace-based test is initiated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend-checkout-shopping-cart&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Frontend:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Checking&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;out&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;shopping&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;cart'&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Simulate user checking out shopping cart&lt;/span&gt;
  &lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
    &lt;span class="na"&gt;httpRequest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://${env:FRONTEND_ADDR}/api/checkout&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Content-Type&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;{&lt;/span&gt;
          &lt;span class="s"&gt;"userId": "2491f868-88f1-4345-8836-d5d8511a9f83",&lt;/span&gt;
          &lt;span class="s"&gt;"email": "someone@example.com",&lt;/span&gt;
          &lt;span class="s"&gt;"address": {&lt;/span&gt;
            &lt;span class="s"&gt;"streetAddress": "1600 Amphitheatre Parkway",&lt;/span&gt;
            &lt;span class="s"&gt;"state": "CA",&lt;/span&gt;
            &lt;span class="s"&gt;"country": "United States",&lt;/span&gt;
            &lt;span class="s"&gt;"city": "Mountain View",&lt;/span&gt;
            &lt;span class="s"&gt;"zipCode": "94043"&lt;/span&gt;
          &lt;span class="s"&gt;},&lt;/span&gt;
          &lt;span class="s"&gt;"userCurrency": "USD",&lt;/span&gt;
          &lt;span class="s"&gt;"creditCard": {&lt;/span&gt;
            &lt;span class="s"&gt;"creditCardCvv": 672,&lt;/span&gt;
            &lt;span class="s"&gt;"creditCardExpirationMonth": 1,&lt;/span&gt;
            &lt;span class="s"&gt;"creditCardExpirationYear": 2030,&lt;/span&gt;
            &lt;span class="s"&gt;"creditCardNumber": "4432-8015-6152-0454"&lt;/span&gt;
          &lt;span class="s"&gt;}&lt;/span&gt;
        &lt;span class="s"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see from the code, this is an http-based trigger that hits the &lt;code&gt;/api/checkout&lt;/code&gt; endpoint. The information needed for the POST is contained in the body section. Running this test will cause the trigger to fire, initiating a checkout process. Since the OpenTelemetry Demo produces a trace for any request, Tracetest can capture both the response of this POST and the distributed trace which the OpenTelemetry Demo app writes to Jaeger. It can then process these results using the test specs defined in the second part of this test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;specs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="general" name="Tracetest trigger"]&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;It&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;called&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;frontend&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;success"&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:tracetest.response.status = &lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="rpc" name="oteldemo.CheckoutService/PlaceOrder" rpc.system="grpc" rpc.method="PlaceOrder" rpc.service="oteldemo.CheckoutService"]&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;was&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;placed"&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:app.user.id = "2491f868-88f1-4345-8836-d5d8511a9f83"&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:app.order.items.count = &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="rpc" name="oteldemo.PaymentService/Charge" rpc.system="grpc" rpc.method="Charge" rpc.service="oteldemo.PaymentService"]&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;was&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;charged"&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:rpc.grpc.status_code  =  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:tracetest.selected_spans.count &amp;gt;= &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="rpc" name="oteldemo.ShippingService/ShipOrder" rpc.system="grpc" rpc.method="ShipOrder" rpc.service="oteldemo.ShippingService"]&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;product&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;was&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;shipped"&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:rpc.grpc.status_code = &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:tracetest.selected_spans.count &amp;gt;= &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="rpc" name="oteldemo.CartService/EmptyCart" rpc.system="grpc" rpc.method="EmptyCart" rpc.service="oteldemo.CartService"]&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;cart&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;was&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;emptied"&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:rpc.grpc.status_code = &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:tracetest.selected_spans.count &amp;gt;= &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These test specs define the assertions to run on specific parts of the data returned from the test. If we look at the first test spec, we can see that it, similar to a black box test, checks against the response data to make sure the HTTP POST returns a status code of 200:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="general" name="Tracetest trigger"]&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;It&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;called&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;frontend&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;success"&lt;/span&gt;  
  &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:tracetest.response.status = &lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More interesting is the next test specification. It looks into the trace attributes being exposed by the PlaceOrder method to make sure that the item count being checked out is equal to 1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="rpc" name="oteldemo.CheckoutService/PlaceOrder" rpc.system="grpc" rpc.method="PlaceOrder" rpc.service="oteldemo.CheckoutService"]&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;was&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;placed"&lt;/span&gt;
  &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:app.user.id = "2491f868-88f1-4345-8836-d5d8511a9f83"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:app.order.items.count = &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This test specification is created in the Tracetest Web UI by simply selecting the span of interest, in this case the CheckoutService/PlaceOrder span.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;tracetest&lt;/span&gt;&lt;span class="nc"&gt;.span.type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"rpc"&lt;/span&gt; &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"oteldemo.CheckoutService/PlaceOrder"&lt;/span&gt; &lt;span class="nt"&gt;rpc&lt;/span&gt;&lt;span class="nc"&gt;.system&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"grpc"&lt;/span&gt; &lt;span class="nt"&gt;rpc&lt;/span&gt;&lt;span class="nc"&gt;.method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"PlaceOrder"&lt;/span&gt; &lt;span class="nt"&gt;rpc&lt;/span&gt;&lt;span class="nc"&gt;.service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;"oteldemo.CheckoutService"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, selecting the attribute of interest, &lt;code&gt;attr:app.order.items.count&lt;/code&gt;, and creating a test specification asserting that this value should equal &lt;code&gt;1&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;attr&lt;/span&gt;&lt;span class="nd"&gt;:app&lt;/span&gt;&lt;span class="nc"&gt;.order.items.count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then name the test specification.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;💡 Have you followed along and installed the OpenTelemetry Demo in Docker and ran the Tracetest tests? If so, go to &lt;a href="http://localhost:11633/"&gt;http://localhost:11633/&lt;/a&gt; to view the UI.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5LchjtoU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692652871/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/CreateAssertion_uo4hch.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5LchjtoU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1692652871/Blogposts/Black%2520box%2520testing%2520against%2520OpenTelemetry%2520Demo/CreateAssertion_uo4hch.gif" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1692652871/Blogposts/Black%20box%20testing%20against%20OpenTelemetry%20Demo/CreateAssertion_uo4hch.gif" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Building tests based on the visibility provided by distributed tracing instrumentation makes end-to-end tests quick and easy to build. This reduction in the time, energy, and expertise needed to build tests makes it possible to provide high quality coverage across the entire distributed application. Once you set these tests up to run either manually or via your CI/CD process with the Tracetest CLI, your developers will be able to deploy changes with confidence.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;💡 Want to read more about how Trace-based Testing overcomes the limits of black box testing and see where it fits in the testing pyramid? Check out this &lt;a href="https://thenewstack.io/where-does-trace-based-testing-fit-in-the-testing-pyramid/"&gt;TheNewStack article&lt;/a&gt;!&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions and Final Remarks
&lt;/h2&gt;

&lt;p&gt;The OpenTelemetry Demo, like many modern applications, contains different languages, services, and numerous technologies. For these types of complex cloud-native architectures, we have seen that black box testing is insufficient. Fortunately, we have also provided a solution!&lt;/p&gt;

&lt;p&gt;With trace-based testing with tools like Tracetest, that leverage existing observability instrumentation, you can enable deep end-to-end testing and reduce the risk of introducing errors when releasing code. It makes developing new features in microservice infrastructures easier and more secure. But, most important, it gives developers more confidence to deploy code with confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus Challenge - Run the Tests Yourself!
&lt;/h2&gt;

&lt;p&gt;Want to see the OpenTelemetry Demo and run Tracetest tests yourself? It takes only four commands to install and run the demo and tests in Docker. Check out the &lt;a href="https://docs.tracetest.io/live-examples/opentelemetry-store/overview"&gt;one page instructions&lt;/a&gt; in the docs!&lt;/p&gt;

&lt;p&gt;Want to learn more about the OpenTelemetry Community Demo? &lt;a href="https://opentelemetry.io/docs/demo/"&gt;Look at the official OpenTelemetry docs&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Want to read more about the trace-based tests by the author of the tests, Daniel? See the &lt;a href="https://opentelemetry.io/blog/2023/testing-otel-demo/"&gt;blog post on the OpenTelemetry blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Have questions for the Tracetest team? Reach out to us on &lt;a href="https://discord.com/channels/884464549347074049/963470167327772703"&gt;Discord&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Want to check out the repo, add an issue with a desired feature, or give Tracetest a star? &lt;a href="https://github.com/kubeshop/tracetest"&gt;Go to our GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>distributedsystems</category>
      <category>cloudnative</category>
      <category>opensource</category>
    </item>
    <item>
      <title>GitHub Actions + Observability + Slack: Synthetic API Tests</title>
      <dc:creator>Ken Hamric</dc:creator>
      <pubDate>Thu, 01 Jun 2023 18:40:28 +0000</pubDate>
      <link>https://dev.to/kubeshop/github-actions-observability-slack-synthetic-api-tests-46kd</link>
      <guid>https://dev.to/kubeshop/github-actions-observability-slack-synthetic-api-tests-46kd</guid>
      <description>&lt;p&gt;Synthetic monitoring is a useful technique that allows you to simulate user transactions executed against your application. This helps you monitor critical API endpoints across different layers of your systems, alerting you to any failure. By proactively testing the API at regular intervals, you can quickly detect issues, investigate them and optimize system performance for your end-users, reducing MTTR.&lt;/p&gt;

&lt;p&gt;Characteristics of synthetic monitoring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is highly consistent, simulating user behavior but with a fixed, predictable test.&lt;/li&gt;
&lt;li&gt;It can be run on a scheduled basis and/or as part of a CI/CD process.&lt;/li&gt;
&lt;li&gt;It can be run in “pre-production”.&lt;/li&gt;
&lt;li&gt;It is typically tied to an alerting mechanism to inform the team of failures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s see how we can use existing, commonly available tooling to build our own synthetic monitoring alerts to cover an API back end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using GitHub Actions to Simulate Synthetic Monitoring
&lt;/h2&gt;

&lt;p&gt;Every major CI environment, including GitHub Actions, is capable of scheduling jobs. In GitHub Actions, we can schedule a workflow by using the &lt;code&gt;on.schedule&lt;/code&gt; attribute and provide a &lt;code&gt;cron&lt;/code&gt; expression to configure how often we want our job to run. If you are not sure how to use &lt;code&gt;cron&lt;/code&gt;, you can use &lt;a href="https://www.freeformatter.com/cron-expression-generator-quartz.html" rel="noopener noreferrer"&gt;generators&lt;/a&gt; to write the expression for you.&lt;/p&gt;

&lt;p&gt;Secondly, we need a test framework to rely on. Traditionally, API synthetic monitoring tools have been limited to conducting simple black box tests. While effective when testing monolithic, synchronous applications, these black box tools are limited in their ability to test deeply across the entire flow triggered by an API call. They do not provide much confidence when building tests against modern, distributed, cloud-native architectures such as microservices or Lambda/FaaS-based systems. &lt;/p&gt;

&lt;p&gt;Luckily, there is a way to utilize observability tools, namely distributed tracing, that are relied on by these complex systems to also empower your testing. The technique is called trace-based testing, and we will be using Tracetest, an open-source tool, to build and run these tests.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For this article, we are considering that you already have a Tracetest instance running either on your CI environment or deployed somewhere. We are also using the sample &lt;a href="https://github.com/kubeshop/pokeshop" rel="noopener noreferrer"&gt;Pokeshop application&lt;/a&gt; as the system under test. You will see an option to install it when &lt;a href="https://docs.tracetest.io/getting-started/detailed-installation#3-select-a-default-installation-or-an-installation-with-sample-app" rel="noopener noreferrer"&gt;installing Tracetest&lt;/a&gt;. If you don’t have Tracetest running yet, check out our &lt;a href="https://docs.tracetest.io/getting-started/installation/" rel="noopener noreferrer"&gt;installation guide&lt;/a&gt;, &lt;a href="https://docs.tracetest.io/examples-tutorials/recipes" rel="noopener noreferrer"&gt;recipes&lt;/a&gt;, and &lt;a href="https://github.com/kubeshop/tracetest/tree/main/examples" rel="noopener noreferrer"&gt;examples&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finally, we need a way to send alerts when tests fail. For this, we will rely on Slack!&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Trace-based Testing with Tracetest in GitHub Actions
&lt;/h2&gt;

&lt;p&gt;What does this Pokeshop application we will be setting up a synthetic monitor for look like? It has two microservices with an asynchronous message queue tying them together. Their jobs are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accept the API call, validate it and put it on a message queue, returning a 200 status code on success.&lt;/li&gt;
&lt;li&gt;The second ‘worker’ microservice gets the request off of the queue and does the ‘real’ work asynchronously.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We want our monitor to validate the full flow, ensuring both services do their jobs. We will be testing a critical API call, a POST to the Pokemon import process. All Pokemon MUST be imported properly!!!&lt;/p&gt;

&lt;p&gt;Considering that you already set up your Tracetest instance, let’s start building our synthetic monitoring tool using it. Let’s create a full test that will verify both microservices execute properly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# monitoring/usecases/user_listing_products.yaml&lt;/span&gt;

&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8jEnYSwVg&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pokeshop - Import&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Import a Pokemon&lt;/span&gt;
  &lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
    &lt;span class="na"&gt;httpRequest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://demo-pokemon-api.demo/pokemon/import&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Content-Type&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{"id":52}'&lt;/span&gt;
  &lt;span class="na"&gt;specs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST should return status code &lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="http" name="POST /pokemon/import" http.method="POST"]&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:http.status_code  =  &lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Validation step in API microservice should validate properly&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="general" name="validate request"]&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:validation.isValid  =  "true"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Import process that pulls message off queue must exist!&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="general" name="import pokemon"]&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:tracetest.selected_spans.count = &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;External request to pokeapi.co should return 'Meowth'&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="http" name="HTTP GET pokeapi.pokemon" http.method="GET"]&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:http.response.body| json_path '$.name' = 'meowth'&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Should insert into pokeshop postgres DB&lt;/span&gt;
    &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="database" name="pg.query:INSERT pokeshop"&lt;/span&gt;
      &lt;span class="s"&gt;db.system="postgresql" db.name="pokeshop" db.user="ashketchum"]&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:tracetest.selected_spans.count = &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have 2 test specifications covering the first microservice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;POST should return status code 200.&lt;/li&gt;
&lt;li&gt;Validation step in API microservice should validate properly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And 3 test specifications covering the second “worker” microservice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import process that pulls a message off the queue must exist!&lt;/li&gt;
&lt;li&gt;External request to &lt;code&gt;pokeapi.co&lt;/code&gt; should return &lt;code&gt;Meowth&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Should insert into the &lt;code&gt;pokeshop&lt;/code&gt; Postgres database.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we have our test, let’s make it run in a GitHub Actions workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This example illustrates how you can use Tracetest to achieve synthetic monitoring&lt;/span&gt;
&lt;span class="c1"&gt;# and get notified via Slack when something fails&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Synthetic monitoring with Tracetest&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# allows the manual trigger&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;run-syntehtic-monitoring&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run synthetic monitoring&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Start app and tracetest&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-compose -f docker-compose.yaml -f tracetest/docker-compose.yaml up -d&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install tracetest CLI&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;curl -L https://raw.githubusercontent.com/kubeshop/tracetest/main/install-cli.sh | bash&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure Tracetest CLI&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tracetest configure -g --endpoint http://localhost:11633 --analytics=false&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run synthetic monitoring tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;tracetest test run -d test-api.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Automated Trace-based Testing with GitHub Actions Schedule
&lt;/h2&gt;

&lt;p&gt;Now we can run our test any time we want by triggering it manually, however, synthetic monitoring requires us to run this test periodically, so, we can use &lt;code&gt;on.schedule&lt;/code&gt; to make GitHub Actions run the workflow automatically on a set time interval:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This example illustrates how you can use Tracetest to achieve synthetic monitoring&lt;/span&gt;
&lt;span class="c1"&gt;# and get notified via Slack when something fails&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Synthetic monitoring with Tracetest&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# allows the manual trigger&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Normally, we run synthetic monitoring in a time schedule. GitHub Actions allows&lt;/span&gt;
  &lt;span class="c1"&gt;# us to achieve that using a cron job. Read more about how cron jobs are configured in&lt;/span&gt;
  &lt;span class="c1"&gt;# this article: https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;# Here are some examples of valid cron strings:&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#- cron: '*/30 * * * *' # every 30 minutes&lt;/span&gt;
  &lt;span class="c1"&gt;#- cron: '*/5 * * * *' # every 5 minutes&lt;/span&gt;
  &lt;span class="c1"&gt;#- cron: '* * * * *' # every minute&lt;/span&gt;
  &lt;span class="c1"&gt;#- cron: '0 */1 * * *' # every hour&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;# For this example, we are going to run the job every 5 minutes&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*/5&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;run-syntehtic-monitoring&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run synthetic monitoring&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Start app and tracetest&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-compose -f docker-compose.yaml -f tracetest/docker-compose.yaml up -d&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install tracetest CLI&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;curl -L https://raw.githubusercontent.com/kubeshop/tracetest/main/install-cli.sh | bash&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure Tracetest CLI&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tracetest configure -g --endpoint http://localhost:11633 --analytics=false&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run synthetic monitoring tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;tracetest test run -d test-api.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Introduce Synthetic Monitoring Alerts with Slack
&lt;/h2&gt;

&lt;p&gt;And, to cover the last aspect of synthetic monitoring, we need a way of receiving alerts when something breaks. For this, we will set up a Slack bot to notify us when the test breaks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For this example, we are going to use &lt;a href="https://api.slack.com/messaging/webhooks" rel="noopener noreferrer"&gt;Slack’s Incoming Webhook&lt;/a&gt; to send messages to a channel.&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This example illustrates how you can use Tracetest to achieve synthetic monitoring&lt;/span&gt;
&lt;span class="c1"&gt;# and get notified via Slack when something fails&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Synthetic monitoring with Tracetest&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# allows the manual trigger&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Normally, we run synthetic monitoring in a time schedule. GitHub Actions allows&lt;/span&gt;
  &lt;span class="c1"&gt;# us to achieve that using a cron job. Read more about how cron jobs are configured in&lt;/span&gt;
  &lt;span class="c1"&gt;# this article: https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;# Here are some examples of valid cron strings:&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;#- cron: '*/30 * * * *' # every 30 minutes&lt;/span&gt;
  &lt;span class="c1"&gt;#- cron: '*/5 * * * *' # every 5 minutes&lt;/span&gt;
  &lt;span class="c1"&gt;#- cron: '* * * * *' # every minute&lt;/span&gt;
  &lt;span class="c1"&gt;#- cron: '0 */1 * * *' # every hour&lt;/span&gt;
  &lt;span class="c1"&gt;#&lt;/span&gt;
  &lt;span class="c1"&gt;# For this example, we are going to run the job every 5 minutes&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;*/5&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;run-syntehtic-monitoring&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run synthetic monitoring&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Start app and tracetest&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-compose -f docker-compose.yaml -f tracetest/docker-compose.yaml up -d&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install tracetest CLI&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;curl -L https://raw.githubusercontent.com/kubeshop/tracetest/main/install-cli.sh | bash&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure Tracetest CLI&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tracetest configure -g --endpoint http://localhost:11633 --analytics=false&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run synthetic monitoring tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;tracetest test run -d test-api.yaml&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Send message on Slack in case of failure&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ failure() }}&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;slackapi/slack-github-action@v1.24.0&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="c1"&gt;# check the block kit builder docs to understand how it works&lt;/span&gt;
          &lt;span class="c1"&gt;# and how to modify it: https://api.slack.com/block-kit&lt;/span&gt;
          &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;{&lt;/span&gt;
              &lt;span class="s"&gt;"blocks": [&lt;/span&gt;
                &lt;span class="s"&gt;{&lt;/span&gt;
                  &lt;span class="s"&gt;"type": "header",&lt;/span&gt;
                  &lt;span class="s"&gt;"text": {&lt;/span&gt;
                    &lt;span class="s"&gt;"type": "plain_text",&lt;/span&gt;
                    &lt;span class="s"&gt;"text": ":warning: Synthetic Monitoring Alert :warning:",&lt;/span&gt;
                    &lt;span class="s"&gt;"emoji": true&lt;/span&gt;
                  &lt;span class="s"&gt;}&lt;/span&gt;
                &lt;span class="s"&gt;},&lt;/span&gt;
                &lt;span class="s"&gt;{&lt;/span&gt;
                  &lt;span class="s"&gt;"type": "section",&lt;/span&gt;
                  &lt;span class="s"&gt;"fields": [&lt;/span&gt;
                    &lt;span class="s"&gt;{&lt;/span&gt;
                      &lt;span class="s"&gt;"type": "mrkdwn",&lt;/span&gt;
                      &lt;span class="s"&gt;"text": "*Status:*\nFailed"&lt;/span&gt;
                    &lt;span class="s"&gt;},&lt;/span&gt;
                    &lt;span class="s"&gt;{&lt;/span&gt;
                      &lt;span class="s"&gt;"type": "mrkdwn",&lt;/span&gt;
                      &lt;span class="s"&gt;"text": "*Pipeline:*\n&amp;lt;${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View workflow&amp;gt;"&lt;/span&gt;
                    &lt;span class="s"&gt;}&lt;/span&gt;
                  &lt;span class="s"&gt;]&lt;/span&gt;
                &lt;span class="s"&gt;}&lt;/span&gt;
              &lt;span class="s"&gt;]&lt;/span&gt;
            &lt;span class="s"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_WEBHOOK_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SLACK_WEBHOOK_URL }}&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_WEBHOOK_TYPE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;INCOMING_WEBHOOK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this configuration, from now on, tests will run every 5 minutes and, if any of them fail, you will receive a message on Slack informing you about it:&lt;/p&gt;

&lt;p&gt;!&lt;a href="https://res.cloudinary.com/djwdcmwdz/image/upload/v1685632757/Blogposts/synthetic-monitoring-github-actions/Untitled_1_nnrvvg.png" rel="noopener noreferrer"&gt;https://res.cloudinary.com/djwdcmwdz/image/upload/v1685632757/Blogposts/synthetic-monitoring-github-actions/Untitled_1_nnrvvg.png&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can check our &lt;a href="https://github.com/kubeshop/tracetest/tree/main/examples/tracetest-synthetic-monitoring" rel="noopener noreferrer"&gt;synthetic monitoring example&lt;/a&gt; on GitHub to see how Tracetest and the demo application were configured.&lt;/p&gt;

&lt;p&gt;Last, but not least - if would you like to learn more about Tracetest and what it brings to the table? Check the &lt;a href="https://docs.tracetest.io/examples-tutorials/recipes/running-tracetest-with-lightstep/" rel="noopener noreferrer"&gt;docs&lt;/a&gt; and try it out by &lt;a href="https://tracetest.io/download" rel="noopener noreferrer"&gt;downloading&lt;/a&gt; it today!&lt;/p&gt;

&lt;p&gt;Also, please feel free to join our &lt;a href="https://discord.com/channels/884464549347074049/963470167327772703" rel="noopener noreferrer"&gt;Discord community&lt;/a&gt;, give &lt;a href="https://github.com/kubeshop/tracetest" rel="noopener noreferrer"&gt;Tracetest a star on GitHub&lt;/a&gt;, or schedule a &lt;a href="http://calendly.com/ken-kubeshop/otel-user-interview-w-tracetest" rel="noopener noreferrer"&gt;time to chat 1:1&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Future
&lt;/h2&gt;

&lt;p&gt;The Tracetest team has been discussing whether to build synthetic API monitoring directly into Tracetest to make creating and running synthetic tests easier. This would involve adding the scheduling of tests and notifications into Tracetest. &lt;/p&gt;

&lt;p&gt;The Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It would make it super convenient to add scheduled tests with notifications.&lt;/li&gt;
&lt;li&gt;For SREs installing Tracetest, it would provide a ready tool for doing deep synthetic tests against the system they are responsible for.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The dev team creating Tracetest would be focused on items outside its core mission of trace-based testing, pulling time from other needed and exciting improvements.&lt;/li&gt;
&lt;li&gt;There are a variety of different ways to notify team members, and it would be difficult to support a wide number of them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Should we leave scheduling and notification to outside services, such as GitHub Actions paired with Slack, or would you like to see this capability embedded in Tracetest? Let us know in &lt;a href="https://www.surveymonkey.com/r/75RFLCH" rel="noopener noreferrer"&gt;this four-question poll&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>cloudnative</category>
      <category>opensource</category>
      <category>sre</category>
    </item>
    <item>
      <title>A Tool for Cloud Native Testing - One Year In</title>
      <dc:creator>Ken Hamric</dc:creator>
      <pubDate>Wed, 26 Apr 2023 22:48:04 +0000</pubDate>
      <link>https://dev.to/kubeshop/a-tool-for-cloud-native-testing-one-year-in-2182</link>
      <guid>https://dev.to/kubeshop/a-tool-for-cloud-native-testing-one-year-in-2182</guid>
      <description>&lt;p&gt;Starting anything from scratch is a challenge. With &lt;a href="https://tracetest.io/"&gt;Tracetest&lt;/a&gt; reaching its one year birthday today, this seemed a good chance to look back on the first year of the project. Hopefully this information will be of interest to other founders considering starting a new open-source project.&lt;/p&gt;

&lt;p&gt;It’s been a rollercoaster ride with amazing highs. In the first year, Tracetest reached &lt;a href="https://star-history.com/#kubeshop/tracetest&amp;amp;Date"&gt;500 stars&lt;/a&gt;, &lt;a href="https://tracetest.io/integrations"&gt;integrated with 9 different products&lt;/a&gt;, including leading tracing provides like &lt;a href="https://tracetest.io/integrations/datadog"&gt;Datadog&lt;/a&gt;, &lt;a href="https://tracetest.io/integrations/lightstep"&gt;Lightstep&lt;/a&gt;, and many more. Let’s celebrate the year, and welcome the next with open arms. Here’s our story of how Tracetest was born and the challenges seen in our first year.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sY2839fr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682451873/Blogposts/one-year-anniversary/tracetest-github-repo_gd8psj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sY2839fr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682451873/Blogposts/one-year-anniversary/tracetest-github-repo_gd8psj.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1682451873/Blogposts/one-year-anniversary/tracetest-github-repo_gd8psj.png" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Product from Scratch
&lt;/h2&gt;

&lt;p&gt;First, what is Tracetest? &lt;a href="https://github.com/kubeshop/tracetest/tree/v0.11.5"&gt;Tracetest&lt;/a&gt; is a testing tool that leverages the data in a distributed trace to enable integration, system and end-to-end tests to be created in a fraction of the time. End-to-end tests are typically difficult to write. They can take 3 to 10 days to build across a complex distributed system. With Tracetest you can build the same test in 20 minutes. That is 24 to 72 times faster. Seriously!&lt;/p&gt;

&lt;p&gt;How? We use a new test type called &lt;a href="https://thenewstack.io/trace-based-testing-the-next-step-in-observability/"&gt;trace-based testing&lt;/a&gt;. Most of the time and complexity involved in building an end-to-end test is in adding code to provide visibility into the systems under test. You have to understand the complete flow, set up connections and permissions to various data stores you may want to inspect to ensure proper operation and find means to introspect components such as microservices and key infrastructure so you can ensure what you believe is happening actually is. Creating the actual assertions, such as “status code should equal 200”, is a trivial part of the work.&lt;/p&gt;

&lt;p&gt;With trace-based testing and Tracetest, the observability of the distributed system under test is provided by the distributed trace you have already instrumented your system to provide. Tracetest can “see” not only the response from API calls to your application, but the full flow and each system involved as documented by the captured distributed trace. With that data, the work to build a test is to simply decide the assertions you want to add.&lt;/p&gt;

&lt;p&gt;Tracetest is &lt;a href="https://github.com/kubeshop/tracetest"&gt;open source&lt;/a&gt;, MIT licensed, and the first MVP release occurred April 26th, 2022. Let's look at some of the challenges and questions faced in this first year, and how we addressed them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Fully Remote Team
&lt;/h2&gt;

&lt;p&gt;My first two startups were bootstrapped, with only myself doing the initial development on the first, and only myself and two co-founders, who were part time, working on the second. It was a great approach in the day, but I believe it is less applicable today. More skill sets are needed to develop a system, from back end, front end, UX, and product management, and it is harder to be able to cover all these talents. There is also a higher level of expectation in the market - we are used to lovely products that are intuitive to use, and it is hard for a generalist to have this level of talent.&lt;/p&gt;

&lt;p&gt;There is also a time to market constraint, as good ideas are quickly copied by well funded potential competitors. Tracetest is fortunate enough to be an incubator project under &lt;a href="https://kubeshop.io/"&gt;Kubeshop&lt;/a&gt;, so this affords us the luxury of recruiting a full development team.&lt;/p&gt;

&lt;p&gt;We began Tracetest last year with resources that were already on staff at Kubeshop, “borrowing” three developers based in Europe. Jasmin, Povilas, and Mahmoud got the project off the ground and the first MVP released in only 3 months. Working with a European-based development team while acting as the product manager was, however, hard, as I was based in Germantown, TN in the CST time zone. With a 6 to 7 hour time difference, the commitment to wake up at 4 or 5 am most days so there was overlap was just not sustainable.&lt;/p&gt;

&lt;p&gt;We made the decision to try to recruit a development team in the Americas. While I had worked with remote developers in Europe before and had seen both the advantages and disadvantages, I did not have experience hiring and working with a team in Central and Latin America. With the help of our recruiter, &lt;a href="https://www.linkedin.com/in/julian-simon-parson-32803a11b/"&gt;Julian at Aura Recruit&lt;/a&gt;, we were able to build a team in just 2 months. This team is a pleasure to work with - Sebastian, Matheus, Oscar, Jorge, and Daniel!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wP3yDQaN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682451184/Blogposts/one-year-anniversary/team_lmstg3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wP3yDQaN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682451184/Blogposts/one-year-anniversary/team_lmstg3.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1682451184/Blogposts/one-year-anniversary/team_lmstg3.png" width="800" height="584"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They are mature, focused on the product in addition to the technology, and are each a leader in their own right. Each acts as a product manager and as a developer relations person, while still holding down their “day job” of being a back-end or front-end developer. If you have ever wondered about hiring a team in the Americas, I can highly recommend it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developing Software Based on a New Concept
&lt;/h2&gt;

&lt;p&gt;Testing tools are hardly new. Testing tools that execute against a back-end application have existed since the 1990s. They typically involve defining a method to trigger a test, perhaps hitting an API, and then creating assertions against the response data.&lt;/p&gt;

&lt;p&gt;Trace-based testing has some entirely new challenges, as you are asserting not only against the response data, but against the distributed trace. The trace is a tree like structure, with activities branching off from the main call.&lt;/p&gt;

&lt;p&gt;One of the main challenges we had was how to write assertions against this tree, as it was not flat like simple response data is. We came up with a solution which will be familiar to front end developers - using a selector. We modeled our selectors on the CSS selector language, and the assertions in Tracetest, called test specs, have two components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A selector specifying what span or spans to apply the assertions against.&lt;/li&gt;
&lt;li&gt;One or more assertions to apply against any of the spans matching the selector.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This decision created some options for very powerful assertions. In one test spec, we can specify that any gRPC process in the system should return a status code of zero. This singular check applies across every call involved in the trace. It is also self maintaining, as it will test any new gRPC calls that are added into the flow for that operation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hyTOBkga--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682450934/Blogposts/one-year-anniversary/All-gRPC-spans_av0ihy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hyTOBkga--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682450934/Blogposts/one-year-anniversary/All-gRPC-spans_av0ihy.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1682450934/Blogposts/one-year-anniversary/All-gRPC-spans_av0ihy.png" width="800" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another decision we faced this year was how to write the tests. We knew we wanted a graphical interface to see the trace and build tests from it. We also knew we needed a way to express the test in code so it could be versioned and used in a CI/CD/GitOps flow. We debated using a language such as JavaScript or Go to express it, but these would not easily handle our assertions which apply against multiple spans. The team decided on a YAML representation, and it was a great choice. It is clean, concise and easily diffed in Git. We express the entire test in this format and the test trigger and test specs are clearly shown.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;phAZcrT4B&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Books list with availability&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Testing the books list and availability check&lt;/span&gt;
  &lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
    &lt;span class="na"&gt;httpRequest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://app:8080/books&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GET&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Content-Type&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
  &lt;span class="na"&gt;specs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="http" name="GET /books" http.target="/books"&lt;/span&gt;
      &lt;span class="s"&gt;http.method="GET"]&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:tracetest.span.duration  &amp;lt; 500ms&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="general" name="Books List"]&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:books.list.count = &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="http" name="GET /availability/:bookId" http.method="GET"]&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:http.host = "availability:8080"&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;span[tracetest.span.type="general" name="Availablity check"]&lt;/span&gt;
    &lt;span class="na"&gt;assertions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;attr:isAvailable = "true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A third challenge was the user interface. With a trace-based test, there is a lot going on! In addition to the normal flows in a test tool, such as seeing a list of tests and test runs and defining a test and seeing the response and having assertions applied against it, we had an entire trace to show and enable test specs to be created against. We have kept Olly, our UX designer, busy. We opted to create our initial versions ‘wrong’, accepting that we needed to see and use it before we could hope to get an elegant flow. It has taken multiple tries, but we now have a version that ‘flows’ as you create tests and view the results.&lt;/p&gt;

&lt;h3&gt;
  
  
  UX - April 26th, 2022 - v0.1 MVP
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sldDboIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682449407/Blogposts/one-year-anniversary/v0.1_trimmed_jvfff7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sldDboIM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682449407/Blogposts/one-year-anniversary/v0.1_trimmed_jvfff7.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1682449407/Blogposts/one-year-anniversary/v0.1_trimmed_jvfff7.png" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  UX - August 26th, 2022 - v0.6
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--in1Cy9m3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682449609/Blogposts/one-year-anniversary/v0.6-trimmed_vwqudv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--in1Cy9m3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682449609/Blogposts/one-year-anniversary/v0.6-trimmed_vwqudv.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1682449609/Blogposts/one-year-anniversary/v0.6-trimmed_vwqudv.png" width="800" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  UX - v0.11, April 26th, 2023
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fsdSrv4k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682449697/Blogposts/one-year-anniversary/v0.11_trimmed_emwtrf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fsdSrv4k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682449697/Blogposts/one-year-anniversary/v0.11_trimmed_emwtrf.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1682449697/Blogposts/one-year-anniversary/v0.11_trimmed_emwtrf.png" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting the Word Out
&lt;/h2&gt;

&lt;p&gt;New concepts are, by definition, new. There is no existing model, and potential users have no prior experience with which to base understanding the new concept. My previous startup, which we began in 2008 and sold in 2016, was named CrossBrowserTesting.com. As you may imagine, it was used to do cross browser testing, providing the ability to do live testing, take screenshots, and do automated selenium testing across a wide range of browsers and devices. It was simple to explain, and with several competitors in the marketplace there was a general understanding of what to expect from the product.&lt;/p&gt;

&lt;p&gt;Tracetest is different. While the name is, once again, very direct, what exactly does it mean to test based on a trace? In addition to this, distributed tracing, upon which it is based, is a concept that is newer and many teams do not have exposure to. This results in a need to spend more energy explaining the problem space and particularly our approach to solving it. Personally, it has resulted in my developing new skills, as explaining and promoting the use of the project fell to me for most of the year.&lt;/p&gt;

&lt;p&gt;In my previous startup, we wrote only 20 blog posts in the first 8 years, at Tracetest we have written 38 in the past year alone, a pace of almost one per week. We have also been producing videos, which was a real challenge as a newcomer to the medium, resulting in many, many retakes. Like any skill, practice makes you better, and while I will be getting no Emmy’s awarded, time at task has made the process easier. We are fortunate to have added a professional developer relations expert to the team, Adnan, so the pace and quality of the work has increased.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O_EE6t5h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682450035/Blogposts/one-year-anniversary/Adnan-at-FOSDEM_sa17fy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O_EE6t5h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682450035/Blogposts/one-year-anniversary/Adnan-at-FOSDEM_sa17fy.jpg" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1682450035/Blogposts/one-year-anniversary/Adnan-at-FOSDEM_sa17fy.jpg" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conferences and speaking engagements are also a new approach for me personally, and we have been to several this year. Adnan recently spoke at FOSDEM, and we both were present at KubeCon + CloudNativeCon Europe in Amsterdam just last week. It is very motivating to present the project in person and receive direct feedback from real experts in the distributed, cloud-native world. We were overwhelmed by the response and crowds at the booth last week, and are reenergized to keep paving a way to making trace-based testing mainstream.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1pyhxgdm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682450280/Blogposts/one-year-anniversary/ken-at-kubecon-europe-2022_qscy5i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1pyhxgdm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682450280/Blogposts/one-year-anniversary/ken-at-kubecon-europe-2022_qscy5i.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1682450280/Blogposts/one-year-anniversary/ken-at-kubecon-europe-2022_qscy5i.png" width="800" height="721"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up the First Year
&lt;/h2&gt;

&lt;p&gt;Wow. It has been a busy, exciting year. As we were demoing Tracetest to hundreds of interested people last week at KubeCon, I was proud of the work the team had done. Tracetest works, and it will revolutionize testing for distributed systems. It flows well and is a pleasure to use. We have had 1000s of downloads, and &lt;a href="https://github.com/kubeshop/tracetest"&gt;https://github.com/kubeshop/tracetest&lt;/a&gt; reached 500 stars on Wednesday at the conference! Getting to 500 stars before the one year anniversary was a goal, and we were excited to exceed expectations. There is still work to be done. We are focused on adding new integrations so the tool works with any distributed tracing solution, whether vendor based such as Datadog, New Relic, Elastic or Lightstep, or open source such as OpenSearch or Jaeger. We are also excited to begin work on some new capabilities being suggested by our users to extend the capabilities of Tracetest, such as the &lt;a href="https://github.com/kubeshop/tracetest/issues/2417"&gt;Ability to export application behavior as policies for runtime&lt;/a&gt; or &lt;a href="https://github.com/kubeshop/tracetest/issues/1470"&gt;Define common trace "patterns / issues / problems"&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Like what we are doing and want to help make our second year even better than the first? Give us a &lt;a href="https://github.com/kubeshop/tracetest"&gt;star on Github&lt;/a&gt;, create an issue there with your thoughts on the direction to take the product, or talk to us on our &lt;a href="https://discord.com/channels/884464549347074049/963470167327772703"&gt;Discord channel&lt;/a&gt;. Looking forward to year #2!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IT6QUo9U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682450410/Blogposts/one-year-anniversary/500-stars_ialhsd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IT6QUo9U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1682450410/Blogposts/one-year-anniversary/500-stars_ialhsd.jpg" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1682450410/Blogposts/one-year-anniversary/500-stars_ialhsd.jpg" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>testing</category>
      <category>observability</category>
      <category>microservices</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>Spring update: Integrations, Improving UX, and Ease of Provisioning</title>
      <dc:creator>Ken Hamric</dc:creator>
      <pubDate>Tue, 11 Apr 2023 16:23:21 +0000</pubDate>
      <link>https://dev.to/kubeshop/spring-update-integrations-improving-ux-and-ease-of-provisioning-5fm9</link>
      <guid>https://dev.to/kubeshop/spring-update-integrations-improving-ux-and-ease-of-provisioning-5fm9</guid>
      <description>&lt;p&gt;Spring has sprung, and Q1 is over! It is a perfect time to look back, see what you’ve done well, and contemplate how to improve moving forward. I want to share some of the highlights I’m most proud of from the Tracetest team in the first quarter of 2023. And also share our roadmap for Q2 moving forward.&lt;/p&gt;

&lt;p&gt;What is Tracetest? It is an &lt;a href="https://github.com/kubeshop/tracetest"&gt;open-source test tool&lt;/a&gt; built for any application using a distributed, cloud-native architecture. It uses the visibility exposed by your existing instrumentation, namely distributed tracing, to allow you to build integration, system, and end-to-end tests that can reach across the entire system. This technique, known as trace-based testing, allows you to assert the proper behavior of all the different microservices, lambda functions, asynchronous processes, and infrastructure components involved in a modern application. It is the ‘easy button’ for your full system tests, allowing you to create tests in orders of magnitude less time, increase your test coverage and improve quality in today’s increasingly fast-paced development and deployment cycles.&lt;/p&gt;

&lt;p&gt;We began the quarter with a couple of major focuses:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Integrations&lt;/li&gt;
&lt;li&gt;Improving ease of use&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s look at what we accomplished in each category.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrations with New Distributed Tracing Solutions
&lt;/h2&gt;

&lt;p&gt;Tracetest works by leveraging the distributed tracing capability you have already instrumented into your application. As part of this, we need to support a wide spectrum of observability and APM tools. We came into the quarter with integrations with multiple tracing solutions, including &lt;a href="https://www.jaegertracing.io/"&gt;Jaeger&lt;/a&gt;, &lt;a href="https://opensearch.org/"&gt;OpenSearch&lt;/a&gt;, &lt;a href="https://grafana.com/oss/tempo/"&gt;Grafana Tempo&lt;/a&gt;, SignalFX, and of course, the &lt;a href="https://opentelemetry.io/docs/collector/"&gt;OpenTelemetry Collector&lt;/a&gt;. This quarter, we added more of the most popular tracing solutions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lightstep
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://lightstep.com/"&gt;Lightstep&lt;/a&gt; is a leading cloud-native reliability platform. &lt;a href="https://twitter.com/adrianamvillela"&gt;Adriana Villela&lt;/a&gt;, a developer advocate from Lightstep, was one of the first users of Tracetest way back in May 2022. Since then, she has been a vocal proponent of trace-based testing and a friend of the Tracetest project. The team worked with her to enable &lt;a href="https://tracetest.io/blog/tracetest-integration-with-lightstep"&gt;Tracetest to interoperate with Lightstep&lt;/a&gt;, enabling an &lt;a href="https://docs.tracetest.io/examples-tutorials/recipes/running-tracetest-with-lightstep"&gt;integration&lt;/a&gt; via the &lt;a href="https://opentelemetry.io/docs/collector/"&gt;OpenTelemetry collector&lt;/a&gt;. Adriana even created a video showing Tracetest and the OTel Demo App running on &lt;a href="https://www.nomadproject.io/"&gt;Hashicorp Nomad&lt;/a&gt; with Lightstep as the back end (of course)!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/EBWf2aaR9wk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Elastic
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.elastic.co/"&gt;Elastic&lt;/a&gt;, the company famous for developing the ELK stack, has a very popular APM solution. Michael Hyatt, a solutions architect for Elastic, &lt;a href="https://github.com/kubeshop/tracetest/issues/1777"&gt;reached out to see if we would add Elastic as a trace data source&lt;/a&gt;, as the Elastic datastore can accept traces whether instrumented with &lt;a href="https://www.elastic.co/guide/en/apm/agent/index.html"&gt;Elastic APM agents&lt;/a&gt; or the default OpenTelemetry instrumentation. Michael was super helpful in assisting the team as we developed and tested the &lt;a href="https://docs.tracetest.io/examples-tutorials/recipes/running-tracetest-with-elasticapm"&gt;Elastic integration&lt;/a&gt;, and even wrote the blog post which appeared on both the &lt;a href="https://tracetest.io/blog/tracetest-integration-elastic-trace-based-testing-application-performance-monitoring"&gt;Tracetest&lt;/a&gt; and &lt;a href="https://www.elastic.co/blog/trace-based-testing-elastic-apm-tracetest"&gt;Elastic&lt;/a&gt; sites.&lt;/p&gt;

&lt;h3&gt;
  
  
  New Relic
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://newrelic.com/"&gt;New Relic&lt;/a&gt; needs no introduction, as it is a well-known observability platform. New Relic supports using the OpenTelemetry collector, so we were able to add it as a trace data source and &lt;a href="https://docs.tracetest.io/configuration/connecting-to-data-stores/new-relic/"&gt;document the process&lt;/a&gt;. The team also documented a use case contained in this recipe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.tracetest.io/examples-tutorials/recipes/running-tracetest-with-new-relic"&gt;Running Tracetest With New Relic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  AWS X-Ray
&lt;/h3&gt;

&lt;p&gt;The integration with &lt;a href="https://aws.amazon.com/xray/"&gt;AWS X-Ray&lt;/a&gt; was initiated due to conversations with two different teams with very similar use patterns. They were both using serverless architectures with AWS and needed a better way to test the critical flows. Few tools serve this area well, but Tracetest is a natural choice for testing modern distributed FaaS flows. The team quickly built an integration to &lt;a href="https://docs.tracetest.io/configuration/connecting-to-data-stores/awsxray/"&gt;retrieve trace data from AWS X-Ray&lt;/a&gt;. As importantly, the team focused on documenting use cases, as there are several options for deploying in AWS. Some of the recipes and use cases include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.tracetest.io/examples-tutorials/recipes/running-tracetest-with-aws-x-ray"&gt;Running Tracetest with AWS X-Ray (AWS X-Ray Node.js SDK)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.tracetest.io/examples-tutorials/recipes/running-tracetest-with-aws-x-ray-adot/"&gt;Running Tracetest with AWS X-Ray (AWS X-Ray Node.js SDK &amp;amp; AWS Distro for OpenTelemetry)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.tracetest.io/examples-tutorials/recipes/running-tracetest-with-aws-terraform"&gt;Running Tracetest on AWS Fargate with Terraform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.tracetest.io/examples-tutorials/recipes/running-tracetest-with-step-functions-terraform"&gt;Running Tracetest with AWS Step Functions, AWS X-Ray and Terraform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.tracetest.io/examples-tutorials/recipes/running-tracetest-with-datadog/"&gt;Running Tracetest with Datadog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cloud Native Tool Integrations
&lt;/h2&gt;

&lt;p&gt;We also wanted to integrate with tools in the Open Source arena that are focused on modern, cloud-native applications. The tools we decided to integrate with this quarter both came from user inquiries asking “Do you work with k6?” and “Can Keptn use trace-based testing?”.&lt;/p&gt;

&lt;h3&gt;
  
  
  k6
&lt;/h3&gt;

&lt;p&gt;The initial thought to add a &lt;a href="https://docs.tracetest.io/tools-and-integrations/k6"&gt;k6 integration&lt;/a&gt; came from Kubecon Detroit, as we had 5 or 6 different people asking “Do you work with k6?”. These k6 users could see the value in having load tests that could assert that the complete flow and all the micro-services involved perform correctly and speedily under load, rather than just having a “black box” test that barely tests past the API gateway. As part of the &lt;a href="https://tracetest.io/blog/announcing-the-tracetest-integration-with-k6-deep-load-testing-of-your-cloud-native-system"&gt;rollout of this capability&lt;/a&gt;, we participated in a wonderful k6 “Office hours” community call with the &lt;a href="https://k6.io/"&gt;k6&lt;/a&gt; team.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Dog70D7aVyg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Keptn
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://docs.tracetest.io/tools-and-integrations/keptn"&gt;Keptn integration&lt;/a&gt; was added based on two GitHub issues raised in the &lt;a href="https://keptn.sh/"&gt;Keptn community&lt;/a&gt; (&lt;a href="https://github.com/keptn/integrations/issues/48"&gt;[integration] Tracetest #48&lt;/a&gt; and &lt;a href="https://github.com/keptn/lifecycle-toolkit/issues/508"&gt;SLO for Traces #508&lt;/a&gt;). The desire was to use the &lt;a href="https://engineering.dynatrace.com/blog/instrumenting-keptn-with-opentelemetry/"&gt;OpenTelemetry instrumentation which has been adopted at the core of Keptn&lt;/a&gt; to enable tests to be built that used data from those traces. The results of these tests will be used as service level indicators as part of Keptn’s control plane to decide whether to deploy new code. The implementation was done using the Keptn Job Executor Service, which you can &lt;a href="https://tracetest.io/blog/announcing-the-tracetest-integration-with-keptn-the-control-plane-for-cloud-native-application-life-cycle-orchestration"&gt;read about here&lt;/a&gt;. Another great experience was getting invited to talk about the integration at the Keptn Community Meeting in February.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.youtube.com/watch?t=778&amp;amp;v=-9X3XTdGK_s&amp;amp;feature=youtu.be" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--YXsKcov_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ytimg.com/vi/-9X3XTdGK_s/maxresdefault.jpg" height="450" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.youtube.com/watch?t=778&amp;amp;v=-9X3XTdGK_s&amp;amp;feature=youtu.be" rel="noopener noreferrer" class="c-link"&gt;
          Keptn Community &amp;amp; Developer Meeting - Feb 1, 2023 - YouTube
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Meeting notes: https://docs.google.com/document/d/1y7a6uaN8fwFJ7IRnvtxSfgz-OGFq6u7bKN6F7NDxKPg/edit Learn more: https://keptn.sh Get started with tutorials: ...
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--WWa10o8f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.youtube.com/s/desktop/932eb6a8/img/favicon.ico" width="16" height="16"&gt;
        youtube.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Testkube
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://testkube.io/"&gt;Testkube&lt;/a&gt; was a natural choice for building an integration. It’s one of 4 other projects under our open-source startup accelerator, &lt;a href="https://kubeshop.io/"&gt;Kubeshop&lt;/a&gt;. Testkube has an adjacent “job to be done” with Tracetest.&lt;/p&gt;

&lt;p&gt;Testkube is a Kubernetes-native testing framework that allows you to write tests with a number of other test frameworks, such as Cypress, k6, Postman, and others. You then run them all via Testkube. It allows you to manage the test orchestration and execution of the various tests and integrate running them into your CI/CD/GitOps pipeline.&lt;/p&gt;

&lt;p&gt;Both Tracetest and Testkube are designed for testing cloud-native applications, and, by integrating with Testkube, we gain some useful capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Orchestration with other tests &lt;a href="https://tracetest.io/blog/event-driven-kubernetes-testing-with-testkube-and-tracetest#running-tests-in-a-test-suite-or-transaction"&gt;to make test suites&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The ability to &lt;a href="https://tracetest.io/blog/event-driven-kubernetes-testing-with-testkube-and-tracetest#running-event-driven-trace-based-tests"&gt;trigger Tracetests based on particular Kubernetes events&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The ability to &lt;a href="https://tracetest.io/blog/event-driven-kubernetes-testing-with-testkube-and-tracetest#running-scheduled-trace-based-tests"&gt;schedule tests&lt;/a&gt;, enabling synthetic monitoring of your back-end distributed system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The use cases were documented in a &lt;a href="https://tracetest.io/blog/event-driven-kubernetes-testing-with-testkube-and-tracetest"&gt;blog post&lt;/a&gt; and a &lt;a href="https://docs.tracetest.io/examples-tutorials/recipes/running-tracetest-with-testkube"&gt;recipe was added&lt;/a&gt; showing how to use Testkube and Tracetest together. We also participated in a workshop with the Testkube team and showcased how both tools work in action.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/nAp3zYgykok"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Improving Ease of Use
&lt;/h2&gt;

&lt;p&gt;Creating a powerful tool introducing a totally new way to test distributed applications is not enough. The tool has to be one you WANT to use. This is continually top of mind for the entire Tracetest team, and we had several areas of improvement for this quarter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transactions and Chaining Tests, v2
&lt;/h3&gt;

&lt;p&gt;Software development is a process, and perfection on the first pass often results in paralysis. With the &lt;a href="https://tracetest.io/blog/v08-release-notes"&gt;release of v0.8 a couple of months earlier&lt;/a&gt;, we introduced the ability to chain tests, have variables in tests, and define environments such as Test, QA, or Prod. To call this a huge release would be accurate, and we knew there were UX flows that could be improved. We documented these and tackled a &lt;a href="https://github.com/kubeshop/tracetest/issues/1655"&gt;‘Chaining V2’ epic&lt;/a&gt; at the beginning of the quarter. Of the 15 issues tackled in this epic, the &lt;a href="https://tracetest.io/blog/ad-hoc-testing-of-distributed-systems"&gt;enabling of ad-hoc tests by prompting for undefined variables&lt;/a&gt; was my favorite. This allows you to leave a particular input “blank”, run a test, and have Tracetest prompt you each time for the value to run the test with. This is particularly useful when developing and you want to test with numerous values interactively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qURI_EdN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1681223505/Blogposts/spring-update/Untitled_go704y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qURI_EdN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1681223505/Blogposts/spring-update/Untitled_go704y.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1681223505/Blogposts/spring-update/Untitled_go704y.png" width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Moving Settings Into the User Interface
&lt;/h3&gt;

&lt;p&gt;With the initial version of Tracetest, we had a configuration file that contained all settings: how to connect to the trace data store, how often to poll for a trace and when to timeout, and a few other settings. This presented several challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The server had to be rebooted to accept any changes to the configuration.&lt;/li&gt;
&lt;li&gt;The sections in the configuration file were hard to document and understand.&lt;/li&gt;
&lt;li&gt;Errors in the configuration file could cause the server not to start.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these issues impacted usability, particularly for new users. In December, &lt;a href="https://tracetest.io/blog/v09-release-notes"&gt;we moved the configuration of the trace data stores into the application&lt;/a&gt;, making a critical, error-prone step much easier to successfully complete. &lt;/p&gt;

&lt;p&gt;This quarter, we completed the process by adding three new tabs - &lt;a href="https://docs.tracetest.io/configuration/analytics"&gt;Analytics&lt;/a&gt;, &lt;a href="https://docs.tracetest.io/configuration/trace-polling"&gt;Trace Polling&lt;/a&gt;, and &lt;a href="https://docs.tracetest.io/configuration/demo"&gt;Demo&lt;/a&gt;. We also added the ability to alter the server configuration via the CLI, making sure any of the changes which can be done on the UI can be done in an automated manner.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d82ao1TP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1681223473/Blogposts/spring-update/screely-1681223348979_zgq7wc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d82ao1TP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/djwdcmwdz/image/upload/v1681223473/Blogposts/spring-update/screely-1681223348979_zgq7wc.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1681223473/Blogposts/spring-update/screely-1681223348979_zgq7wc.png" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Multiple Ways to Provision a New Install
&lt;/h3&gt;

&lt;p&gt;Speaking of being able to configure a server from the command line, the team added multiple ways to configure a server. These include &lt;a href="https://docs.tracetest.io/configuration/provisioning"&gt;using a provisioning file&lt;/a&gt; to “hydrate” the server and passing the provisioning file as a &lt;a href="https://docs.tracetest.io/configuration/server"&gt;base64 encoded string via an environment variable&lt;/a&gt;, perfect when deploying Tracetest in an ECS cluster so there is no need to mount a file. The only “required” data to start the Tracetest server is the Postgres connection information, and it can now be &lt;a href="https://docs.tracetest.io/configuration/server"&gt;passed as environment variables as well as via a configuration file&lt;/a&gt;. This capability was covered in detail in our March community call:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/U_94bEptrrE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking Forward
&lt;/h2&gt;

&lt;p&gt;For Q2, the team will be doubling down on integrations, with plans to add Azure Application Insights, Google Cloud Trace, and Honeycomb as supported trace data stores. We are also looking for a couple of tool integrations to add and would &lt;a href="https://github.com/kubeshop/tracetest/issues/new?assignees=&amp;amp;labels=feature+request%2C+triage&amp;amp;template=feature_request.md&amp;amp;title="&gt;love your ideas and input&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One area we are considering investing in is enabling Tracetest tests to be run as a synthetic monitor against your API, enabling you to schedule Tracetest tests and be alerted when they fail. This would enable deep end-to-end tests to be easily created and used to “keep an eye on” and alert the SRE and DevOps teams about potential failures. We would love your thoughts on using trace-based tests for synthetic monitoring - do you need it!? &lt;a href="https://discord.com/channels/884464549347074049/963470167327772703"&gt;Let us know in Discord&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Adnan and I will be at the Tracetest booth in KubeCon Europe this month! Come by, see us, and discuss any and all things OpenTelemetry, distributed tracing, testing, trace-based testing, and Tracetest. Would love to show you the tool, get your thoughts, and hear your ideas. Reach out to &lt;a href="https://www.linkedin.com/in/ken-hamric-016b1420/"&gt;myself&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/adnanrahic/"&gt;Adnan&lt;/a&gt; on LinkedIn and we will set up a time for a chat!&lt;/p&gt;

&lt;p&gt;Lastly, our birthday is coming up. Tracetest will be 1 year old on April 26th!!! We have a goal of hitting 500 stars by our birthday. We are currently at 474, so we need your help at &lt;a href="https://github.com/kubeshop/tracetest"&gt;github.com/kubeshop/tracetest&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>cloudnative</category>
      <category>testing</category>
      <category>distributedsystems</category>
      <category>sre</category>
    </item>
    <item>
      <title>Announcing the Tracetest integration with k6: Deep Load Testing of your Cloud Native System</title>
      <dc:creator>Ken Hamric</dc:creator>
      <pubDate>Sun, 05 Mar 2023 21:28:13 +0000</pubDate>
      <link>https://dev.to/kubeshop/announcing-the-tracetest-integration-with-k6-deep-load-testing-of-your-cloud-native-system-287</link>
      <guid>https://dev.to/kubeshop/announcing-the-tracetest-integration-with-k6-deep-load-testing-of-your-cloud-native-system-287</guid>
      <description>&lt;p&gt;Today, we're happily announcing that &lt;a href="https://tracetest.io/"&gt;Tracetest&lt;/a&gt; now works with &lt;a href="https://k6.io/"&gt;k6&lt;/a&gt;, a modern load-testing tool used by thousands of developers worldwide. The combination of k6 and Tracetest allows your load tests to check across your entire microservice, FaaS, or Kubernetes-based applications.&lt;/p&gt;

&lt;p&gt;This checks that not only the top surface of the application returns the correct information and remains performant, but allows you to test and verify across the full distributed application, making sure none of the many services involve begin failing or taking too long under load.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xo7jX-jN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/djwdcmwdz/image/upload/v1677495246/Blogposts/k6-tracetest-partnership/Screenshot_2023-02-27_at_11.52.24_niv29x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xo7jX-jN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/djwdcmwdz/image/upload/v1677495246/Blogposts/k6-tracetest-partnership/Screenshot_2023-02-27_at_11.52.24_niv29x.png" alt="https://res.cloudinary.com/djwdcmwdz/image/upload/v1677495246/Blogposts/k6-tracetest-partnership/Screenshot_2023-02-27_at_11.52.24_niv29x.png" width="880" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Load Testing Across a Distributed Application
&lt;/h2&gt;

&lt;p&gt;Oscar, one of the developers of the &lt;a href="https://github.com/kubeshop/xk6-tracetest"&gt;k6-tracetest extension&lt;/a&gt;, shows why the combo is so potent:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.loom.com/embed/5c5e1261bb0b4fefa30081294378908c"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TsxaXeOc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/djwdcmwdz/image/upload/v1677495412/Blogposts/k6-tracetest-partnership/k6-Load_Testing_Across_a_Distributed_Application_pnbi12.png" alt="" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is k6?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/grafana/k6"&gt;k6&lt;/a&gt; allows you to &lt;a href="https://k6.io/docs/"&gt;build performant load tests&lt;/a&gt; that take a fraction of the resources legacy load-testing tools require. The tests are written in an easy-to-follow JavaScript form and can be extended with a number of extensions. The tests execute via a Go-JavaScript compiler so they take a minimal amount of resources when being executed, allowing the scaling of load tests with fewer resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Tracetest?
&lt;/h2&gt;

&lt;p&gt;Tracetest is an &lt;a href="https://github.com/kubeshop/tracetest"&gt;open-source CNCF project&lt;/a&gt;. It allows you to &lt;a href="https://docs.tracetest.io/"&gt;quickly build integration and end-to-end tests&lt;/a&gt;, supercharged by your existing distributed traces. The use of your existing distributed traces as part of the test enables assertions to be created across multiple microservices or parts of your distributed application.&lt;/p&gt;

&lt;p&gt;Tracetest makes it possible to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define tests and assertions against every single microservice that a request goes through.&lt;/li&gt;
&lt;li&gt;Work with your existing distributed tracing solution, allowing you to build tests based on your already instrumented system.&lt;/li&gt;
&lt;li&gt;Define multiple transaction triggers, such as a GET against an API endpoint, a gRPC request, etc.&lt;/li&gt;
&lt;li&gt;Return both the response data and a full trace.&lt;/li&gt;
&lt;li&gt;Define assertions against both the response and trace data, ensuring both your response and the underlying processes worked correctly, quickly, and without errors.&lt;/li&gt;
&lt;li&gt;Save tests.&lt;/li&gt;
&lt;li&gt;Run the tests manually or, via CI, build jobs with the Tracetest CLI.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tracetest Now Works with k6!
&lt;/h2&gt;

&lt;p&gt;Tracetest now works with k6, allowing you to conduct load tests that verify your entire distributed application.&lt;/p&gt;

&lt;p&gt;Most load-testing tools will trigger your application and apply tests against the response from the call. As you scale up the number of tests running concurrently, the system under test will be exercised. Assertions can be defined against any of the response data, whether it is the status codes, parts of the response body, or expected timing.&lt;/p&gt;

&lt;p&gt;By including Tracetest in the k6 load test, you can test against both the response AND the information contained in the trace. This allows you to define powerful assertions against all the processes involved in servicing the call invoked by a load test. Some examples of checks it enables include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checking the microservices on “the other side” of a message queue to verify it can handle the load. Typically when load-testing complex systems with message queues you cannot easily assert against the entire system, particularly when it has asynchronous calls.&lt;/li&gt;
&lt;li&gt;In one assertion, assert that all database queries across all microservices should return in less than 100ms, and verify this under load.&lt;/li&gt;
&lt;li&gt;Or that every gRPC process in the entire stack continues returning status codes of zero as the load increases.&lt;/li&gt;
&lt;li&gt;Showing you graphically, via the trace, where any detected failures occur across any of the runs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The ability to observe and assert against the entire system under load, empowered by your current APM or observability platform, makes Tracetest and k6 a powerful combination.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try Tracetest with k6
&lt;/h2&gt;

&lt;p&gt;Tracetest is &lt;a href="https://github.com/kubeshop/tracetest"&gt;open-source&lt;/a&gt; and easy to install. First, install Tracetest CLI. Check out the &lt;a href="https://tracetest.io/download"&gt;download page&lt;/a&gt; for more info. From here, follow the &lt;a href="https://docs.tracetest.io/getting-started/installation"&gt;official documentation&lt;/a&gt; to install the Tracetest server.&lt;/p&gt;

&lt;p&gt;Once the server is installed, open up Tracetest Web UI in the browser and define where Tracetest gets the traces from, whether Jaeger, Lightstep, Elastic, or any trace vendor. You can even send traces to Tracetest via the &lt;a href="https://opentelemetry.io/docs/collector/"&gt;OpenTelemetry collector&lt;/a&gt;. Check out the &lt;a href="https://docs.tracetest.io/configuration/overview"&gt;Configuration Overview&lt;/a&gt; for help!&lt;/p&gt;

&lt;p&gt;Once you have Tracetest working and can run trace-based tests against your distributed system, you will want to create a load test with k6. Use the &lt;a href="https://k6.io/docs/get-started/"&gt;excellent k6 docs to get started&lt;/a&gt;. You can then utilize the &lt;a href="https://github.com/kubeshop/xk6-tracetest"&gt;k6-tracetest extension&lt;/a&gt; to run deep load tests. We have full documentation on how to use k6 and Tracetest together at &lt;a href="https://docs.tracetest.io/tools-and-integrations/k6"&gt;https://docs.tracetest.io/tools-and-integrations/k6&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Tracetest team recently discussed the integration during the k6 Office Hours:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Dog70D7aVyg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZoxXDC0a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/djwdcmwdz/image/upload/v1677495485/Blogposts/k6-tracetest-partnership/try-tracetest-with-k6_ynbr93.png" alt="" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;This is the first version of the integration between k6 and Tracetest. Have any ideas for improving it? Interested in enabling trace-based testing for other load testing tools? Let us know by &lt;a href="https://github.com/kubeshop/tracetest/issues/new/choose"&gt;creating an issue in Github&lt;/a&gt;, or start a conversation with the team behind Tracetest in our &lt;a href="https://discord.com/channels/884464549347074049/963470167327772703"&gt;Discord community&lt;/a&gt;. You can also reach out to us to &lt;a href="http://calendly.com/ken-kubeshop/otel-user-interview-w-tracetest"&gt;schedule a call&lt;/a&gt; to discuss your particular needs or get assistance.&lt;/p&gt;

&lt;p&gt;Excited about the Tracetest project and trace-based testing? Give &lt;a href="https://github.com/kubeshop/tracetest"&gt;Tracetest a star on GitHub&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>observability</category>
      <category>testing</category>
      <category>cloudnative</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
