<?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: Francis Luz</title>
    <description>The latest articles on DEV Community by Francis Luz (@francisluz).</description>
    <link>https://dev.to/francisluz</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F440655%2F895e6a2f-cf13-4788-9130-a499767fec4b.jpeg</url>
      <title>DEV Community: Francis Luz</title>
      <link>https://dev.to/francisluz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/francisluz"/>
    <language>en</language>
    <item>
      <title>How I built Entry's homepage preview</title>
      <dc:creator>Francis Luz</dc:creator>
      <pubDate>Thu, 22 Oct 2026 13:59:51 +0000</pubDate>
      <link>https://dev.to/francisluz/how-i-built-entrys-homepage-preview-hni</link>
      <guid>https://dev.to/francisluz/how-i-built-entrys-homepage-preview-hni</guid>
      <description>&lt;p&gt;My about.me page hadn't changed in 13 years. I wanted a personal homepage, but I didn't want another place where I had to keep rewriting the same information.&lt;/p&gt;

&lt;p&gt;I'm Francis, a software engineer in Dublin, and that's why I started building Entry.&lt;/p&gt;

&lt;p&gt;The preview lets you paste a GitHub user or organisation, a website or an X handle. It drafts a homepage from what you've already published. You don't need an account to try it. &lt;/p&gt;

&lt;p&gt;I wanted to trace each item back to its source. I also needed a way to stop someone from taking another person's public information and publishing it as their own. &lt;/p&gt;

&lt;h2&gt;
  
  
  What Entry reads
&lt;/h2&gt;

&lt;p&gt;You can give the preview up to three sources, plus ten other profile links.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For GitHub&lt;/strong&gt;, Entry reads your name, bio, photo, location, website, linked accounts, pinned repositories and profile README. If there are no pinned repositories, it uses your latest public ones. It reads these through GitHub's public API using Entry's own token.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For a website&lt;/strong&gt;, it reads the page you provide and up to two about or work pages on the same site. It looks for the title, description, structured data, and links to profiles and projects. It respects robots.txt and doesn't take images.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For X&lt;/strong&gt;, it reads your name, bio, photo, website and location through FxTwitter and vxtwitter. It doesn't use the X API or read posts or followers. If the account is protected or the mirrors aren't responding, Entry keeps it as a plain link.&lt;/p&gt;

&lt;p&gt;Other profiles stay as links. Entry doesn't open LinkedIn, Instagram, YouTube, TikTok, Bluesky, Mastodon, Threads, Dribbble, Behance, Medium, Substack, DEV, GitLab, Codeberg or Figma.&lt;/p&gt;

&lt;h2&gt;
  
  
  Websites that need JavaScript
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Simplified example, not Entry's production code.&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;route&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;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;route&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;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&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;allowedTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;document&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="s2"&gt;script&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="s2"&gt;xhr&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="s2"&gt;fetch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;allowedTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resourceType&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;safeFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fulfill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&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;Some personal sites return an empty page until their JavaScript runs. Entry can read those using a browser on the server.&lt;/p&gt;

&lt;p&gt;That browser has no direct network access. Every request goes back through Entry's normal checks. It allows the documents, scripts and data requests needed to read the page, while blocking images, fonts, styles, frames, sockets and beacons. It keeps only the information read from the page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Showing where the information came from
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Simplified example, not Entry's actual schema.&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Provenance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;github&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;website&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;readAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;Every item in the draft has a source listed under "Where this came from".&lt;/p&gt;

&lt;p&gt;Each item records the source, the URL it was read from, the field it came from and when it was read. That's what you can check if a description looks wrong or a project is missing.&lt;/p&gt;

&lt;p&gt;If there's little public information, the draft is short. Entry doesn't add text just to fill the page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where AI fits
&lt;/h2&gt;

&lt;p&gt;The preview can suggest wording changes for the headline, About text and project descriptions.&lt;/p&gt;

&lt;p&gt;It makes one request through Vercel AI Gateway after the draft has appeared. That request contains text from the first source, including the name, headline, bio, location and up to six project descriptions, with a fixed length limit. It doesn't include your handle, IP address, cookies or account details.&lt;/p&gt;

&lt;p&gt;Entry then checks the suggestions in code. It rejects any that introduce a link, name, employer, number or date that wasn't in the source text, or that change the language.&lt;/p&gt;

&lt;p&gt;The suggestions appear beside the draft with a label. You choose whether to apply them.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Entry doesn't use this content to train models. The provider may retain requests under its own terms. I haven't arranged zero data retention, and the privacy policy says that.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Proving ownership before publishing
&lt;/h2&gt;

&lt;p&gt;Anyone can preview public sources. That also means someone can preview a profile that isn't theirs.&lt;/p&gt;

&lt;p&gt;Claiming a preview copies it into your editor. Anything imported stays off your public page until you prove you control the source.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For GitHub&lt;/strong&gt;, you sign in through an OAuth app used only for verification. Entry checks that the account matches the source, or that you're an admin if the source is an organisation. It revokes and discards the token straight away without storing it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For a website&lt;/strong&gt;, you can add a DNS record, a meta tag or a &lt;code&gt;rel="me"&lt;/code&gt; link containing your verification code or Entry address. Entry checks the proof each time you verify.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For X&lt;/strong&gt;, you can put a code in your bio or add links in both directions between your X profile and a source you've already verified.&lt;/p&gt;

&lt;p&gt;Verification codes are random and expire after seven days. They aren't secrets, since you publish them as proof. Each account gets up to ten verification attempts an hour.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the preview stores
&lt;/h2&gt;

&lt;p&gt;A preview lasts 24 hours from the time you create it. Using it doesn't extend that deadline. You can also remove it immediately with "Delete my preview". It has no public address.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;entry_preview&lt;/code&gt; cookie lasts 24 hours and contains a random key. It's HttpOnly, and the database stores a one-way hash of that key.&lt;/p&gt;

&lt;p&gt;Entry caches public source information for up to a day, using the public handle as the cache key. That avoids fetching the same profile repeatedly. The cache doesn't store information about who requested it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For rate limits&lt;/strong&gt;, Entry uses a daily HMAC value derived from the IP address, date and a secret key. The value changes each day, and the counters expire within a day. The preview doesn't store or log the IP address. Vercel BotID also runs on the preview page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Simplified example of the daily rate-limit key.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hmacSha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;|&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;utcDate&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server records daily totals for previews started, drafts created, claims, verifications and publications, along with draft time. With consent, Google Analytics receives only source types and counts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I used
&lt;/h2&gt;

&lt;p&gt;Entry runs on Next.js and Vercel, with Convex for the database, file storage and sign-in backend. I'm building it on my own.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's still rough
&lt;/h2&gt;

&lt;p&gt;X depends on two unofficial mirrors. If neither works, the profile stays as a link.&lt;/p&gt;

&lt;p&gt;Export currently means emailing &lt;a href="mailto:privacy@entry.fyi"&gt;privacy@entry.fyi&lt;/a&gt;. There's no self-serve option yet.&lt;/p&gt;

&lt;p&gt;The writing studio is new, and most of the example pages are still my own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The preview is at &lt;a href="https://entry.fyi/try" rel="noopener noreferrer"&gt;entry.fyi/try&lt;/a&gt;. You can try it without an account, and Entry deletes the preview after 24 hours.&lt;/p&gt;

&lt;p&gt;I'd like to hear what it missed or got wrong about your GitHub or website. I'm also interested in whether the source labels help you check the draft, and whether the ownership checks feel reasonable.&lt;/p&gt;

&lt;p&gt;Entry has a free plan. Pro is €9 a month for your own domain, more sources and more scans.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>privacy</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Why unit test culture is broken</title>
      <dc:creator>Francis Luz</dc:creator>
      <pubDate>Mon, 03 Aug 2020 23:41:20 +0000</pubDate>
      <link>https://dev.to/francisluz/why-unit-test-culture-is-broken-5f55</link>
      <guid>https://dev.to/francisluz/why-unit-test-culture-is-broken-5f55</guid>
      <description>&lt;p&gt;Write unit tests should be as fun as writing your feature code, no matter which language you're using, it's all code at the end of the day.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it can be improved
&lt;/h2&gt;

&lt;p&gt;Sending the right message is key in my point of view to improve your unit test culture, you don't write unit tests because of the most advanced framework or the best methodology out there.&lt;/p&gt;

&lt;p&gt;They exist as a tool to help you to achieve the goals, which is to have a stable, reliable and documented codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the tools help
&lt;/h2&gt;

&lt;p&gt;The framework will help you to mock calls to external sources that sometimes are 3rd party libraries, that we may don't need wanna include in your test cases.&lt;/p&gt;

&lt;p&gt;The methodology let's say &lt;a href="https://en.wikipedia.org/wiki/Test-driven_development"&gt;TDD(Test-Driven Development)&lt;/a&gt; is a really helpful one, but I don't think that it's the only way of doing it, depends on your project, if there's legacy code, the timing of task and so on. You may find yourself writing together or at the end of your feature code. &lt;/p&gt;

&lt;h2&gt;
  
  
  Let's have a bit of fun
&lt;/h2&gt;

&lt;p&gt;Just to have some code here, and if you're at the beginning of your developer journey let's see how a simple test looks like in python.&lt;/p&gt;

&lt;p&gt;A python class that prints the greetings message as ASCII art and return the base string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;art&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HelloClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HELLO_MSG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello world, "&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greetings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;f"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HELLO_MSG&lt;/span&gt;&lt;span class="si"&gt;}{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;text_art&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text2art&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text_art&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then its unit test will be like this one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;python_class&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HelloClass&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestHelloClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_greetings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;hello_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HelloClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hello_class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;greetings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'developer'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;'Hello world, developer'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Make sure that you plan the right time for your task, a unit test can be sometimes 40% of it, adapt to your project's needs and if the culture is broken, include it step-by-step. &lt;/p&gt;

&lt;p&gt;It's not easy to unit test a whole codebase that hasn't been planned to have it before. That's my main point from the title, the unit test culture could be broken for a variate of reasons, but there's always a room for improvements.&lt;/p&gt;

&lt;p&gt;Hope you enjoy it, that's my personal option about it and based on my experience.&lt;/p&gt;

</description>
      <category>python</category>
      <category>javascript</category>
      <category>unittest</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
