<?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: Javeed Shaik</title>
    <description>The latest articles on DEV Community by Javeed Shaik (@javeed450sudo).</description>
    <link>https://dev.to/javeed450sudo</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%2F4062074%2Ffccd9e27-eb0a-4a29-82ff-e751ca379772.png</url>
      <title>DEV Community: Javeed Shaik</title>
      <link>https://dev.to/javeed450sudo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/javeed450sudo"/>
    <language>en</language>
    <item>
      <title>Three times this week a tool said it worked, and it had not</title>
      <dc:creator>Javeed Shaik</dc:creator>
      <pubDate>Tue, 04 Aug 2026 10:27:05 +0000</pubDate>
      <link>https://dev.to/javeed450sudo/three-times-this-week-a-tool-said-it-worked-and-it-had-not-4hjn</link>
      <guid>https://dev.to/javeed450sudo/three-times-this-week-a-tool-said-it-worked-and-it-had-not-4hjn</guid>
      <description>&lt;p&gt;Three times this week a tool told me it had done something, and it had not. Not one of them threw an error. Each looked exactly like success, and each was caught only because I went and checked the actual artefact afterwards.&lt;/p&gt;

&lt;p&gt;I maintain a set of calculators and a small formula library, so most of my week is arithmetic and DOM. None of these bugs were exotic. That is the point — they are the ordinary kind, the kind that ships.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Grepping HTML for a word is not reading a page
&lt;/h2&gt;

&lt;p&gt;I needed to know whether a set of pages had been updated to a new standard. The obvious move: fetch each page, search the HTML for the marker string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"0.55"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Twelve of them came back positive. Great — except several of those pages plainly did not mention the standard anywhere in their text.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;0.55&lt;/code&gt; was matching inline CSS. &lt;code&gt;opacity: 0.55&lt;/code&gt;, &lt;code&gt;rgba(0,0,0,0.55)&lt;/code&gt;, a transition duration. My "is this page updated" check was counting stylesheet values.&lt;/p&gt;

&lt;p&gt;Worse, the failure was silent and &lt;em&gt;confident&lt;/em&gt;. I did not get an error or an empty result — I got a plausible number that led to a wrong conclusion, and the conclusion was about to go out in an email to someone who would check it.&lt;/p&gt;

&lt;p&gt;The same class of bug had bitten me a month earlier, testing whether an account was verified with &lt;code&gt;'verified' in html.lower()&lt;/code&gt;. That matched the word "verified" in unrelated page furniture and returned true for everything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What actually works:&lt;/strong&gt; match a &lt;em&gt;structural&lt;/em&gt; marker, not a bare string — a class name, an element, an attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;badge-verified&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;          &lt;span class="c1"&gt;# a class the page only emits when true
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or skip the HTML entirely and read the rendered text. Raw HTML contains CSS, JSON blobs, script bodies, nav boilerplate and comments. Any word or number you search for lives in all of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Setting &lt;code&gt;.value&lt;/code&gt; is not filling in a form
&lt;/h2&gt;

&lt;p&gt;I needed to update a bio on a site built with a modern JS framework. Set the textarea's value, click save, done:&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="nx"&gt;textarea&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;NEW_BIO&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;saveButton&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tool reported success. The editor showed my new text. I clicked save. The page said it saved.&lt;/p&gt;

&lt;p&gt;The live profile still had the old bio.&lt;/p&gt;

&lt;p&gt;Assigning to &lt;code&gt;.value&lt;/code&gt; mutates the DOM node, but React keeps its own copy of the state and never notices. On submit it serialises &lt;strong&gt;its&lt;/strong&gt; state — the old value — and posts that. Nothing errors, because from the framework's perspective nothing happened.&lt;/p&gt;

&lt;p&gt;The fix is to go through the native setter so the framework's synthetic &lt;code&gt;onChange&lt;/code&gt; actually fires:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOwnPropertyDescriptor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;HTMLTextAreaElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;setter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;textarea&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NEW_BIO&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;textarea&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input&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;bubbles&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="nx"&gt;textarea&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change&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;bubbles&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React patches &lt;code&gt;value&lt;/code&gt; on the element instance, so calling the &lt;em&gt;prototype's&lt;/em&gt; setter writes the real value underneath and the subsequent &lt;code&gt;input&lt;/code&gt; event makes React pick it up.&lt;/p&gt;

&lt;p&gt;I have now hit this on four different sites. Every time, the tooling said it worked.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. A backgrounded tab gets zero animation frames
&lt;/h2&gt;

&lt;p&gt;This one was a phantom. I was testing a calculator whose result counts up to its final value with a small &lt;code&gt;requestAnimationFrame&lt;/code&gt; tween. Every automated check reported the headline number as &lt;code&gt;0.0&lt;/code&gt;. The supporting rows underneath were all correct. It looked like a real bug in exactly one code path.&lt;/p&gt;

&lt;p&gt;It was not a bug. The tab was not visible, and browsers do not run &lt;code&gt;requestAnimationFrame&lt;/code&gt; callbacks in a backgrounded tab. The tween's first frame fires synchronously — at &lt;code&gt;t = 0&lt;/code&gt;, so it renders the starting value — and the next frame never comes. The readout freezes at zero and looks broken.&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;visibilityState&lt;/span&gt;  &lt;span class="c1"&gt;// "hidden"  &amp;lt;- that was the whole story&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My next move made it much worse. I patched &lt;code&gt;requestAnimationFrame&lt;/code&gt; to a &lt;code&gt;setTimeout&lt;/code&gt; so the tween would complete. Something else on the page ran a perpetual animation loop, that loop was now a tight timer loop, and the renderer froze hard enough to need a reload.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The lesson is narrower than "don't patch globals":&lt;/strong&gt; if a value only renders during animation, do not try to force the animation. Read something that is not animated. The un-tweened rows were right there, computed by the same function, and they told me the arithmetic was fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  The thing they have in common
&lt;/h2&gt;

&lt;p&gt;None of these were logic errors. In all three, the code I wrote did exactly what I told it to. What failed was the &lt;strong&gt;signal I used to decide it had worked&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;grep said "found it" — it had found something else&lt;/li&gt;
&lt;li&gt;the DOM said "value set" — the framework disagreed&lt;/li&gt;
&lt;li&gt;the readout said &lt;code&gt;0.0&lt;/code&gt; — the environment could not render anything else&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every one of them was caught the same way: by looking at the finished artefact instead of the report about the artefact. Read the live page, not the editor. Read the rendered text, not the HTML. Read the value that is not being animated.&lt;/p&gt;

&lt;p&gt;That sounds obvious written down. It is much less obvious at the moment you are doing it, because a tool returning success is genuinely good evidence most of the time — which is exactly what makes the exceptions expensive. A test that reports success while testing nothing is worse than no test at all.&lt;/p&gt;

&lt;p&gt;The habit I have landed on is small: after any write I cannot see the effect of, fetch the thing fresh and assert on it. It costs a few seconds. All three of these would have shipped without it, and one of them nearly went out in an email.&lt;/p&gt;




&lt;p&gt;The calculators this came out of are at &lt;a href="https://healthycalculatorhub.com" rel="noopener noreferrer"&gt;Healthy Calculator Hub&lt;/a&gt;, and the formula library is &lt;a href="https://www.npmjs.com/package/health-fitness-formulas" rel="noopener noreferrer"&gt;&lt;code&gt;health-fitness-formulas&lt;/code&gt;&lt;/a&gt; if you want the tested implementations.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>testing</category>
      <category>debugging</category>
    </item>
    <item>
      <title>A formula can be implemented perfectly and still give the wrong answer</title>
      <dc:creator>Javeed Shaik</dc:creator>
      <pubDate>Tue, 04 Aug 2026 09:14:31 +0000</pubDate>
      <link>https://dev.to/javeed450sudo/a-formula-can-be-implemented-perfectly-and-still-give-the-wrong-answer-2d37</link>
      <guid>https://dev.to/javeed450sudo/a-formula-can-be-implemented-perfectly-and-still-give-the-wrong-answer-2d37</guid>
      <description>&lt;p&gt;I spent a while this year writing a small zero-dependency library of health and fitness formulas — BMI, Mifflin-St Jeor, the US Navy body-fat equation, FFMI, Epley and Brzycki, Karvonen. Thirty-odd functions, no dependencies, ESM, one file.&lt;/p&gt;

&lt;p&gt;It should have been a boring job. It mostly was. But three things came out of it that I think generalise well beyond fitness maths, and one of them genuinely changed how I think about what "correct" means in a library.&lt;/p&gt;

&lt;h2&gt;
  
  
  The boring part: these equations get reimplemented constantly, and quietly wrong
&lt;/h2&gt;

&lt;p&gt;Search for any of these formulas and you will find dozens of implementations. A lot of them are subtly broken, in ways that never throw and never look wrong:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The wrong coefficient set.&lt;/strong&gt; The Navy body-fat equation has separate male and female forms, and separate metric and imperial constants. Four combinations, and three of them are wrong for any given call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The imperial equation fed metric input.&lt;/strong&gt; Nothing errors. You just get a number that is wrong by a believable margin, which is the worst kind of wrong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rounding in the middle.&lt;/strong&gt; More on this below, because it turned out to be the interesting one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these produce a &lt;code&gt;NaN&lt;/code&gt; or a stack trace. They produce a plausible number. That is the entire problem: there is no failure signal, so the bug survives indefinitely.&lt;/p&gt;

&lt;p&gt;My response was unremarkable — every function names the paper it came from in a docblock, and nothing is rounded inside the library. You round for display, because only you know how many decimal places your UI has room for.&lt;/p&gt;

&lt;h2&gt;
  
  
  The interesting part: rounding order is observable, so it has to be pinned
&lt;/h2&gt;

&lt;p&gt;Total daily energy expenditure is BMR times an activity multiplier. Trivial. Except: do you round the BMR before multiplying, or round only the final figure?&lt;/p&gt;

&lt;p&gt;It matters, and it is measurable:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;sex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;female&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;kg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;70.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;167&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;41&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;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;bmrMifflinStJeor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// 1382.75&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;round&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;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.725&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// 2386  &amp;lt;- round first&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;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.725&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;              &lt;span class="c1"&gt;// 2385  &amp;lt;- round last&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One kilocalorie. Utterly meaningless physiologically — nobody's diet is sensitive to 1 kcal, and the underlying equation has a standard error hundreds of times larger.&lt;/p&gt;

&lt;p&gt;But it is not meaningless as a &lt;em&gt;library contract&lt;/em&gt;. Two callers doing "the same" calculation get different numbers, and neither can tell why. Someone comparing my output against another tool finds an off-by-one and reasonably concludes one of us has a bug. So the order is pinned and there is a test that fails if anyone changes it:&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="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="s1"&gt;tdee — rounding order is observable, so it is pinned&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="c1"&gt;// 70.5 kg gives a fractional BMR; rounding first vs last must differ here.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;sex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;female&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;kg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;70.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;167&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;41&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;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;bmrMifflinStJeor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;notEqual&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;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test input must produce a fractional BMR&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;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tdee&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tdee&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;round&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;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.725&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;Note the second assertion. The test asserts &lt;em&gt;its own premise&lt;/em&gt; — that this input actually produces a fractional BMR. Without it, someone tweaking the Mifflin-St Jeor constants could make the input round cleanly, and the test would keep passing while testing nothing at all. A test whose premise can silently evaporate is worse than no test, because it reports success.&lt;/p&gt;

&lt;p&gt;That is the pattern I would take to any numeric library: when a choice is arbitrary but observable, pin it in a test, and make the test verify that its own scenario is still meaningful.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that actually changed my mind: correct is not the same as current
&lt;/h2&gt;

&lt;p&gt;Here is the one I did not see coming.&lt;/p&gt;

&lt;p&gt;The US Navy body-fat equation — Hodgdon &amp;amp; Beckett, 1984 — is the most widely implemented formula in this entire space. My implementation of it is correct. It matches the paper, it matches the reference values, it is tested to one decimal place.&lt;/p&gt;

&lt;p&gt;And partway through the year it stopped being the right answer to the question most people are actually asking.&lt;/p&gt;

&lt;p&gt;The US Department of Defense moved every service to a waist-to-height ratio screen on 1 January 2026, and the Army implemented it on 7 July 2026 — retiring both the height/weight tables and the circumference tape test that produced a body-fat percentage. Someone calling a function to check whether they meet a service standard is now being measured against something that no longer exists. The arithmetic is still right. The &lt;em&gt;answer&lt;/em&gt; is wrong.&lt;/p&gt;

&lt;p&gt;Out of curiosity I audited the calculators that rank for this. Of nine pages I could verify, eight were still running the retired method. Several advertise themselves as updated for 2026. One stamps "Last Logic Update: July 2026" in its footer — the month of the change — while running a formula that was superseded in 2023.&lt;/p&gt;

&lt;p&gt;I do not think those are careless people. I think it is a structural blind spot in how we test numeric code. My test suite verifies that &lt;code&gt;bodyFatNavy&lt;/code&gt; matches Hodgdon &amp;amp; Beckett. There is no test anywhere that could tell me Hodgdon &amp;amp; Beckett stopped being the standard, because that fact does not live in the code, the inputs, or the outputs. It lives in a policy document I had no reason to read.&lt;/p&gt;

&lt;p&gt;The best I have come up with is modest: say plainly, in the docs, what a function is &lt;em&gt;for&lt;/em&gt; and what it is &lt;em&gt;not&lt;/em&gt;, and give the reader the current alternative. So the README now says the Navy equation is named for its origin and not its current use, notes that it remains a sound field estimate, and points at &lt;code&gt;waistToHeightRatio&lt;/code&gt; for the standard that actually applies. Whether anyone reads that is another question — but at least the library is no longer silently implying something false.&lt;/p&gt;

&lt;p&gt;If you maintain anything that encodes an external standard — tax bands, postal formats, accessibility thresholds, compliance rules — I would ask the same question I had to ask myself: &lt;strong&gt;what would have to change in the world for my correct code to start giving wrong answers, and would I ever find out?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Small thing: throw, do not return NaN
&lt;/h2&gt;

&lt;p&gt;Last one, quickly. Every function validates and throws:&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="nf"&gt;bodyFatNavy&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;sex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;male&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;neckCm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;waistCm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;heightCm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;175&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="c1"&gt;// RangeError — waist must exceed neck&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A neck larger than a waist is not a number problem, it is a measurement problem, and &lt;code&gt;NaN&lt;/code&gt; propagates silently through arithmetic until it surfaces somewhere unrelated. Throwing at the boundary makes the caller deal with it while they still have the context to understand it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The library
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/health-fitness-formulas" rel="noopener noreferrer"&gt;&lt;code&gt;health-fitness-formulas&lt;/code&gt;&lt;/a&gt; — MIT, zero dependencies, ESM, Node 18+. 31 tests via &lt;code&gt;node --test&lt;/code&gt;, no test framework.&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;health-fitness-formulas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are the implementations behind the calculators on &lt;a href="https://healthycalculatorhub.com" rel="noopener noreferrer"&gt;Healthy Calculator Hub&lt;/a&gt;, and the suite asserts they stay in agreement with what the site serves. If you spot a coefficient I have got wrong, I would genuinely like to know.&lt;/p&gt;

&lt;p&gt;One honest caveat, since it is a health topic: every function returns a population-level estimate. None is diagnostic, and body-fat categories in particular are conventions rather than an agreed international standard. It does arithmetic on published formulas and shows its working. That is all it does.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>testing</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Three things Indian finance code gets wrong (with the numbers)</title>
      <dc:creator>Javeed Shaik</dc:creator>
      <pubDate>Tue, 04 Aug 2026 08:55:59 +0000</pubDate>
      <link>https://dev.to/javeed450sudo/three-things-indian-finance-code-gets-wrong-with-the-numbers-3hm0</link>
      <guid>https://dev.to/javeed450sudo/three-things-indian-finance-code-gets-wrong-with-the-numbers-3hm0</guid>
      <description>&lt;p&gt;I maintain a set of finance calculators for India. Every formula ships with a unit test, and the&lt;br&gt;
build fails if a number drifts more than 0.5% from a verified value. That sounds like overkill for&lt;br&gt;
arithmetic until you find out how much published finance code is quietly wrong.&lt;/p&gt;

&lt;p&gt;Here are three errors I keep running into, with the actual figures. All three are asserted by tests&lt;br&gt;
in &lt;a href="https://www.npmjs.com/package/indian-finance-formulas" rel="noopener noreferrer"&gt;&lt;code&gt;indian-finance-formulas&lt;/code&gt;&lt;/a&gt;, a&lt;br&gt;
zero-dependency MIT package I extracted from the site.&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;indian-finance-formulas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  1. GST interest is charged on the cash ledger, not the gross bill
&lt;/h2&gt;

&lt;p&gt;This is the most common one, and it is expensive.&lt;/p&gt;

&lt;p&gt;Rule 88B(1) of the CGST Rules charges interest on the tax &lt;strong&gt;actually debited from your electronic&lt;br&gt;
cash ledger&lt;/strong&gt; — not on your gross output liability. If part of your liability was settled through&lt;br&gt;
input tax credit, that part does not attract interest.&lt;/p&gt;

&lt;p&gt;Plenty of code runs the interest on the whole output tax. The difference is not subtle:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;gstInterest&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;indian-finance-formulas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;gstInterest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;    &lt;span class="c1"&gt;// 443.84  — correct: ₹30,000 actually paid in cash&lt;/span&gt;
&lt;span class="nf"&gt;gstInterest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// 1479.45 — the common error: gross liability&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.33× too high.&lt;/strong&gt; On a real filing that is the difference between a rounding error and a number&lt;br&gt;
you would argue about.&lt;/p&gt;

&lt;p&gt;The fix is a naming discipline as much as a maths one. The parameter is called &lt;code&gt;cashTaxPaid&lt;/code&gt;, not&lt;br&gt;
&lt;code&gt;taxAmount&lt;/code&gt;, so it is hard to pass the wrong thing without noticing.&lt;/p&gt;


&lt;h2&gt;
  
  
  2. A step-up SIP does not beat a flat SIP of the same total outlay
&lt;/h2&gt;

&lt;p&gt;Every step-up SIP calculator I have seen shows the step-up winning. It does win — but only because&lt;br&gt;
more money goes in. That is not a strategy insight, it is arithmetic about deposits.&lt;/p&gt;

&lt;p&gt;Hold the &lt;strong&gt;money&lt;/strong&gt; constant instead of the starting instalment, and it reverses:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stepUpSip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sipFutureValue&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;indian-finance-formulas&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;step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;stepUpSip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// ₹1,98,88,715 on ₹68,73,000 invested — start ₹10k/mo, +10% a year, 12% p.a., 20 years&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;flat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sipFutureValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invested&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;240&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// ₹2,86,13,098 on the SAME ₹68,73,000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The flat schedule finishes &lt;strong&gt;₹87 lakh ahead&lt;/strong&gt; on identical money. The reason is simple once you see&lt;br&gt;
it: in a step-up plan, most of the rupees arrive late and compound for fewer years. A flat plan&lt;br&gt;
front-loads the same total, so every rupee gets longer in the market.&lt;/p&gt;

&lt;p&gt;Step-up SIPs are still a perfectly good idea — they match rising income, and most people genuinely&lt;br&gt;
cannot invest the flat-equivalent amount in year one. But the reason to use one is &lt;strong&gt;behavioural,&lt;br&gt;
not mathematical&lt;/strong&gt;, and calculators that imply otherwise are selling a free lunch.&lt;/p&gt;

&lt;p&gt;This one is a test, not a comment, because it is exactly the kind of thing a well-meaning&lt;br&gt;
"optimisation" would silently break:&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="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;flat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;step&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;futureValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. The Section 87A rebate is a cliff, and needs marginal relief
&lt;/h2&gt;

&lt;p&gt;Under India's new tax regime, a rebate takes your tax to zero up to ₹12,00,000 of taxable income.&lt;br&gt;
Implement that naively and earning one rupee more costs you far more than one rupee — the classic&lt;br&gt;
cliff.&lt;/p&gt;

&lt;p&gt;Marginal relief caps the tax at the amount of income above the threshold:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;incomeTaxNewRegime&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;indian-finance-formulas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;incomeTaxNewRegime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1200000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// 0&lt;/span&gt;
&lt;span class="nf"&gt;incomeTaxNewRegime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1200100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// 104     — ₹100 over the line, ₹104 of tax (incl. 4% cess)&lt;/span&gt;
&lt;span class="nf"&gt;incomeTaxNewRegime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1210000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// 10,400&lt;/span&gt;
&lt;span class="nf"&gt;incomeTaxNewRegime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1250000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// 52,000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without relief, the ₹12,00,100 case would jump to tens of thousands. Also asserted by a test.&lt;/p&gt;




&lt;h2&gt;
  
  
  The bit that generalises: statutory values are parameters, not constants
&lt;/h2&gt;

&lt;p&gt;Every function that depends on a notified figure takes it as an argument with a documented default:&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="nf"&gt;gratuity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                        &lt;span class="c1"&gt;// ₹20,00,000 ceiling — most employees&lt;/span&gt;
&lt;span class="nf"&gt;gratuity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ceiling&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2500000&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;  &lt;span class="c1"&gt;// ₹25,00,000 — Central Govt civil employees&lt;/span&gt;

&lt;span class="nf"&gt;incomeTaxNewRegime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1600000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                 &lt;span class="c1"&gt;// FY 2026-27 slabs by default&lt;/span&gt;
&lt;span class="nf"&gt;incomeTaxNewRegime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1600000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;slabs&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;// yours, the day they change&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hard-coding a slab table means waiting for a release when the Finance Act moves. Making it an&lt;br&gt;
argument means the person who noticed can fix it that afternoon.&lt;/p&gt;




&lt;h2&gt;
  
  
  And the failure mode tests cannot catch
&lt;/h2&gt;

&lt;p&gt;Unit tests protect the arithmetic. They cannot protect the &lt;strong&gt;inputs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I hit a clean example of this today. I was building a table of India's 7th Pay Commission pay&lt;br&gt;
matrix and went to the primary source — the Commission's own report — rather than trusting my&lt;br&gt;
notes. It lists Level 13 entry pay as &lt;strong&gt;₹1,18,500&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That figure is wrong today. The CCS (Revised Pay) (Amendment) Rules, 2017 re-based Level 13 and the&lt;br&gt;
correct figure is &lt;strong&gt;₹1,23,100&lt;/strong&gt;. The number printed in the primary source has been superseded for&lt;br&gt;
years.&lt;/p&gt;

&lt;p&gt;No test catches that. The arithmetic stays perfectly correct while the answer is wrong, and&lt;br&gt;
"I checked the official source" is exactly the reasoning that gets you there. The only defence is&lt;br&gt;
citing and &lt;strong&gt;dating&lt;/strong&gt; each statutory figure, so a human can re-check what a machine cannot.&lt;/p&gt;

&lt;p&gt;That is why the calculators carry a source list and a date rather than a vague "updated recently".&lt;/p&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Package: &lt;a href="https://www.npmjs.com/package/indian-finance-formulas" rel="noopener noreferrer"&gt;&lt;code&gt;indian-finance-formulas&lt;/code&gt;&lt;/a&gt; — MIT, zero dependencies, 20 tests&lt;/li&gt;
&lt;li&gt;Source: &lt;a href="https://github.com/javeed450-sudo/indian-finance-formulas" rel="noopener noreferrer"&gt;github.com/javeed450-sudo/indian-finance-formulas&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The calculators these came from: &lt;a href="https://emicalcs.com" rel="noopener noreferrer"&gt;emicalcs.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the suite with &lt;code&gt;npm test&lt;/code&gt; — plain &lt;code&gt;node --test&lt;/code&gt;, no framework. The three traps above are in&lt;br&gt;
there deliberately, so a regression that reintroduces one fails loudly.&lt;/p&gt;

&lt;p&gt;If you have hit a fourth one, I would genuinely like to hear it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>opensource</category>
      <category>testing</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
