<?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: Samyar Shafiee</title>
    <description>The latest articles on DEV Community by Samyar Shafiee (@samyrrrrrr990).</description>
    <link>https://dev.to/samyrrrrrr990</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%2F4182795%2F13c133b4-9d75-48c1-99d7-49e5fb7a7583.jpg</url>
      <title>DEV Community: Samyar Shafiee</title>
      <link>https://dev.to/samyrrrrrr990</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/samyrrrrrr990"/>
    <language>en</language>
    <item>
      <title>My 300 unit tests passed while my lead finder returned "Refund Policy" as a person</title>
      <dc:creator>Samyar Shafiee</dc:creator>
      <pubDate>Tue, 13 Oct 2026 17:27:04 +0000</pubDate>
      <link>https://dev.to/samyrrrrrr990/my-300-unit-tests-passed-while-my-lead-finder-returned-refund-policy-as-a-person-35b</link>
      <guid>https://dev.to/samyrrrrrr990/my-300-unit-tests-passed-while-my-lead-finder-returned-refund-policy-as-a-person-35b</guid>
      <description>&lt;p&gt;I build &lt;a href="https://github.com/Samyrrrrrr990/openleads" rel="noopener noreferrer"&gt;OpenLeads&lt;/a&gt;, an open-source tool that finds people and their work emails from public data. You type "dentists in Austin", it searches OpenStreetMap, the companies' own team pages, and a few other public sources, and it labels every email it returns as &lt;strong&gt;found&lt;/strong&gt;, &lt;strong&gt;pattern&lt;/strong&gt;, or &lt;strong&gt;guessed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For a few months it had a green test suite and a broken product. This is how that happened, and the one change that fixed it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every test mocked the network
&lt;/h2&gt;

&lt;p&gt;OpenLeads talks to a lot of things it doesn't control: the Overpass API, GitHub, OpenAlex, SEC EDGAR, Wikidata, and thousands of small business websites. So the unit tests did what unit tests do. They fed in recorded responses and checked the parsing.&lt;/p&gt;

&lt;p&gt;300 tests. All green. Meanwhile, real searches looked like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"marketing agencies in Miami" returned 20 "people", and 6 of them were page headings like &lt;em&gt;Refund Policy&lt;/em&gt; and &lt;em&gt;HSBC North America&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;"dentists in Austin" returned chiropractors and transport companies.&lt;/li&gt;
&lt;li&gt;"machine learning researchers" returned nothing at all.&lt;/li&gt;
&lt;li&gt;"rust developers in Berlin" was still running after four minutes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these were parsing bugs, so none of them could show up in a parsing test. They were &lt;em&gt;quality&lt;/em&gt; bugs: the code did exactly what it was written to do, against data that didn't look like the fixtures.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: a benchmark against live data, every night
&lt;/h2&gt;

&lt;p&gt;I added a command, &lt;code&gt;openleads bench&lt;/code&gt;, that runs 12 real searches against the live sources and scores the results:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did the search return anything?&lt;/li&gt;
&lt;li&gt;What share of the requested leads came back?&lt;/li&gt;
&lt;li&gt;How many "names" are junk (headings, acronyms, company names)?&lt;/li&gt;
&lt;li&gt;How many emails are backed by evidence, and how many are guesses?&lt;/li&gt;
&lt;li&gt;How long did it take?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A GitHub Actions workflow runs it every night and commits the scoreboard to the repo as &lt;a href="https://github.com/Samyrrrrrr990/openleads/blob/main/BENCHMARK.md" rel="noopener noreferrer"&gt;BENCHMARK.md&lt;/a&gt;. The project website reads the same JSON, so the numbers on the landing page are last night's numbers, not a marketing claim.&lt;/p&gt;

&lt;p&gt;The first run was humbling. The latest one: 12 of 12 searches return results, 82% of requested leads are filled, 0% junk names, and 57% of emails are found or built from a pattern the company really uses. The rest are labeled as guesses, and you decide whether to send them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three things the benchmark taught me
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Telling a name from a heading is hard.&lt;/strong&gt; Capitalized two-word strings on a team page are usually names, until they're "Refund Policy". What finally worked was requiring scraped names to start with a known given name, using public-domain Social Security Administration data plus an international list, and rejecting acronyms outright.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. SMTP verification mostly doesn't run.&lt;/strong&gt; Port 25 is blocked on almost every home connection and cloud VM, so the classic "ask the mail server if this address exists" check usually can't happen. Most real confidence comes from addresses the company publishes itself (in commits, on its site, in &lt;code&gt;security.txt&lt;/code&gt;), which reveal its email format.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Public APIs fall over.&lt;/strong&gt; The public Overpass API returns 504s under load, so local search falls back to a mirror and then to Nominatim. Without a live benchmark, I'd never have known how often that path ran.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd tell anyone with a scraper or an LLM pipeline
&lt;/h2&gt;

&lt;p&gt;Your unit tests check that the code does what you wrote. They can't tell you whether what you wrote is any good against today's data. If your product's output depends on data you don't control, keep a small set of real queries, run them on a schedule, and commit the scores where you'll see them change.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pipx &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s2"&gt;"openleads[all]"&lt;/span&gt;
openleads find &lt;span class="s2"&gt;"dentists in Austin"&lt;/span&gt;
openleads web    &lt;span class="c"&gt;# dashboard with an n8n-style workflow canvas&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxavwgmoywt1oobk6plc8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxavwgmoywt1oobk6plc8.gif" alt="A test run on the OpenLeads workflow canvas" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's AGPL-3.0, runs on your machine, and needs no API keys. It also works as an MCP server for Claude and Cursor. If you find a search that comes back wrong, post it in &lt;a href="https://github.com/Samyrrrrrr990/openleads/discussions/13" rel="noopener noreferrer"&gt;this thread&lt;/a&gt; and it becomes a benchmark case.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/Samyrrrrrr990/openleads" rel="noopener noreferrer"&gt;https://github.com/Samyrrrrrr990/openleads&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>testing</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
