亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

Table of Contents
Correctness: What we really want
Visualization model of program correctness
Testing and correctness
Type and correctness
Put them together
Home Web Front-end CSS Tutorial Types or Tests: Why Not Both?

Types or Tests: Why Not Both?

Apr 19, 2025 am 09:50 AM

Types or Tests: Why Not Both?

There is a debate now and then about the value of typed JavaScript. "Write more tests!" some opponents shouted. "Replace unit tests with types!" others shouted. Both are right in some ways and wrong in others. Twitter's space is not enough to reflect the subtleties. But in this article, we can try to elaborate a reasonable argument on how and how the two should coexist.

Correctness: What we really want

It's best to start with the results. What we really want from all these meta-engineering is correctness . I'm not referring to a strict theoretical computer science definition, but a more general adherence to program behavior and its norms: there is an idea in our mind about how programs work, and the programming process organizes bits and bytes, making this idea a reality. Because we don't always know exactly what we want, and we want to be sure that our program doesn't break when making changes, we write types and tests on top of existing original code just to make things work in the first place.

So if we accept that correctness is what we want and that types and tests are just automated ways to achieve this, it is better to have an intuitive model to show how types and tests help us achieve correctness, thus understanding where they overlap and where they complement each other.

Visualization model of program correctness

If we imagine the entire infinite Turing-complete possible space of all the operations that a program may perform ( including errors ) as a huge gray area, then what we want the program to perform, our specification, is a very, very small subset of that possible space (the green rhombus in the figure below, exaggerated in size to display something):

Our job in programming is to align our programs with specifications as much as possible (of course, we know that we are imperfect, our specifications are constantly changing, such as due to human errors, new features, or unspecified behavior; therefore we never completely manage to achieve complete overlap):

Note again that for the purposes of our discussion here, the boundaries of procedural behavior also include both planned and unplanned errors . Our meaning of “correctness” includes planned errors, but not unplanned errors.

Testing and correctness

We write tests to make sure our program meets our expectations, but there are many options for what to test:

The ideal test is the orange dots in the figure – they accurately test whether our program overlaps the specification. In this visualization we don't really distinguish between test types, but you can think of unit tests as very small points, and integration/end-to-end testing is the big points. Either way, they are points, because no test can fully describe every path in the program. (In fact, you can have 100% code coverage, but still can't test every path because there is a combination explosion!)

The blue dot in the picture is a bad test. Of course, it tests whether our program works, but it doesn't actually pin it to the underlying specification (at the end of the day, what we really want to get from the program). This test breaks when we fix the program to align more closely with the specification, giving us a false positive.

The purple dot is a valuable test because it tests how we think the program should work and determines areas where the program is not currently working. Leading with purple testing and fixing the program implementation accordingly is also known as test-driven development .

The red test in the picture is a rare test. It is not a normal (orange) test that tests the "happy path" (including the wrong state of the plan), but a test that expects and validates the " unhappy path" failed. If this test "passes" where it should "fail," it's a huge early warning sign that something is wrong -- but it's basically impossible to write enough tests to cover the huge possible unhappy paths that exist outside the spec green area. It is rare to find that testing things that shouldn't work is valuable, so they don't do it; but when things go wrong, it can still be a helpful early warning sign.

Type and correctness

If the test is a single point in the probability space where the program may perform an operation, the type represents the category that divides the entire part from the total probability space. We can visualize them as rectangles:

We choose a rectangle to compare the diamonds representing the program, because no type system itself can use types to fully describe our program behavior. (To give a simple example, an id that should always be a positive integer is a numeric type, but numeric types also accept fractions and negative numbers. Apart from very simple union of numeric literals, it is impossible to limit numeric types to a specific range.)

Types act as a constraint on where the program can run when you write your code. If our program starts to exceed the specified boundary of the program type, our type checker (such as TypeScript or Flow) will simply refuse to let us compile the program. This is good because in a dynamic language like JavaScript, it's easy to accidentally create a crash program that is certainly not the one you want to create. The easiest value added is automatic null value checking. If foo does not have a method named bar, calling foo.bar() will result in the well-known undefined is not a function runtime exception. If foo is fully typed, you can catch this issue by the type checker at the time of writing and point out the problematic lines of code (and with the accompanying benefits of autocomplete). This is something that testing simply cannot do.

We may want to write strict types for our programs as if we were trying to write as small as possible rectangles that still conform to our specifications. However, this has a learning curve, because leveraging the type system involves learning completely new syntax and operators as well as the syntax of generic type logic that is necessary to simulate the full dynamic range of JavaScript. Manuals and cheat sheets help lower the learning curve, and more investment is needed here.

Fortunately, this adoption/learning curve doesn't have to stop us. Since type checking is an optional process for Flow, and the configurable stringency of TypeScript (the ability to selectively ignore the problematic lines of code), we can choose from within the scope of type safety. We can even model this:

Larger rectangles, like the big red rectangle in the above image, indicate very loose adoption of the type system of the code base—for example, allowing implicitAny and relying entirely on type inference to simply limit our program from the worst coding.

Medium stringency (like medium-sized green rectangles) can indicate more faithful typeification, but there are a lot of vulnerabilities, such as using explicit any instances and manual type assertions throughout the code base. Nevertheless, even with such lightweight typing, the possible surface area of ??effective programs that do not match our specifications will be greatly reduced.

Maximum rigorousness, like purple rectangles, makes things so tight that it sometimes finds unconforming parts of your program (those are usually unplanned errors in program behavior). Looking for errors in existing programs like this is a very common case in teams that convert a normal JavaScript code base. However, getting the maximum type safety from our type checker may require leveraging generic types and special operators designed to refine and narrow down possible type spaces for each variable and function.

Note that we don't have to write programs before writing types. After all, we just want our types to closely simulate our specifications, so we can actually write our types first and then populate the implementation later. In theory, this would be type-driven development ; in practice, few people actually develop this way, because types penetrate and intertwin with our actual program code.

Put them together

What we ultimately want to build is an intuitive visualization that illustrates how types and tests complement each other in ensuring the correctness of the program.

Our tests assert that our program is specifically performed as expected in the selected critical path (although, as mentioned above, there are certain other test variants, the vast majority of tests do so). In the visual languages ??we have developed, they "fix" the program's dark green rhombus to the canonical light green rhombus. Any movement of the program will destroy these tests, which will cause them to alert. it's great! Testing also has unlimited flexibility and configurability for the most customized use cases.

Our type asserts that our program will not be out of our control by forbidding possible failure modes beyond the boundaries we draw, hoping to surround our specification as closely as possible. In our visual language, they "contain" the possible drift of programs that deviate from the norm (because we always have flaws, and every mistake we make adds additional failures to our programs). Types are also blunt, but powerful (because of type inference and editor tools) tools that benefit from a strong community that provides types that you don't have to write from scratch.

in short:

  • Testing is best at ensuring that the happy path works.
  • Types are best at preventing unhappy paths from existing.

Use them together according to their strengths for the best results!

If you want to learn more about how types and tests cross over, Gary Bernhardt’s great speech on Boundaries and Kent C. Dodds’ Test Trophy has had a significant impact on my thinking about this post.

The above is the detailed content of Types or Tests: Why Not Both?. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

PHP Tutorial
1488
72
CSS tutorial for creating loading spinners and animations CSS tutorial for creating loading spinners and animations Jul 07, 2025 am 12:07 AM

There are three ways to create a CSS loading rotator: 1. Use the basic rotator of borders to achieve simple animation through HTML and CSS; 2. Use a custom rotator of multiple points to achieve the jump effect through different delay times; 3. Add a rotator in the button and switch classes through JavaScript to display the loading status. Each approach emphasizes the importance of design details such as color, size, accessibility and performance optimization to enhance the user experience.

Addressing CSS Browser Compatibility issues and prefixes Addressing CSS Browser Compatibility issues and prefixes Jul 07, 2025 am 01:44 AM

To deal with CSS browser compatibility and prefix issues, you need to understand the differences in browser support and use vendor prefixes reasonably. 1. Understand common problems such as Flexbox and Grid support, position:sticky invalid, and animation performance is different; 2. Check CanIuse confirmation feature support status; 3. Correctly use -webkit-, -moz-, -ms-, -o- and other manufacturer prefixes; 4. It is recommended to use Autoprefixer to automatically add prefixes; 5. Install PostCSS and configure browserslist to specify the target browser; 6. Automatically handle compatibility during construction; 7. Modernizr detection features can be used for old projects; 8. No need to pursue consistency of all browsers,

What is the difference between display: inline, display: block, and display: inline-block? What is the difference between display: inline, display: block, and display: inline-block? Jul 11, 2025 am 03:25 AM

Themaindifferencesbetweendisplay:inline,block,andinline-blockinHTML/CSSarelayoutbehavior,spaceusage,andstylingcontrol.1.Inlineelementsflowwithtext,don’tstartonnewlines,ignorewidth/height,andonlyapplyhorizontalpadding/margins—idealforinlinetextstyling

Styling visited links differently with CSS Styling visited links differently with CSS Jul 11, 2025 am 03:26 AM

Setting the style of links you have visited can improve the user experience, especially in content-intensive websites to help users navigate better. 1. Use CSS's: visited pseudo-class to define the style of the visited link, such as color changes; 2. Note that the browser only allows modification of some attributes due to privacy restrictions; 3. The color selection should be coordinated with the overall style to avoid abruptness; 4. The mobile terminal may not display this effect, and it is recommended to combine it with other visual prompts such as icon auxiliary logos.

Creating custom shapes with css clip-path Creating custom shapes with css clip-path Jul 09, 2025 am 01:29 AM

Use the clip-path attribute of CSS to crop elements into custom shapes, such as triangles, circular notches, polygons, etc., without relying on pictures or SVGs. Its advantages include: 1. Supports a variety of basic shapes such as circle, ellipse, polygon, etc.; 2. Responsive adjustment and adaptable to mobile terminals; 3. Easy to animation, and can be combined with hover or JavaScript to achieve dynamic effects; 4. It does not affect the layout flow, and only crops the display area. Common usages are such as circular clip-path:circle (50pxatcenter) and triangle clip-path:polygon (50%0%, 100 0%, 0 0%). Notice

What is the CSS Painting API? What is the CSS Painting API? Jul 04, 2025 am 02:16 AM

TheCSSPaintingAPIenablesdynamicimagegenerationinCSSusingJavaScript.1.DeveloperscreateaPaintWorkletclasswithapaint()method.2.TheyregisteritviaregisterPaint().3.ThecustompaintfunctionisthenusedinCSSpropertieslikebackground-image.Thisallowsfordynamicvis

How to create responsive images using CSS? How to create responsive images using CSS? Jul 15, 2025 am 01:10 AM

To create responsive images using CSS, it can be mainly achieved through the following methods: 1. Use max-width:100% and height:auto to allow the image to adapt to the container width while maintaining the proportion; 2. Use HTML's srcset and sizes attributes to intelligently load the image sources adapted to different screens; 3. Use object-fit and object-position to control image cropping and focus display. Together, these methods ensure that the images are presented clearly and beautifully on different devices.

What are common CSS browser inconsistencies? What are common CSS browser inconsistencies? Jul 26, 2025 am 07:04 AM

Different browsers have differences in CSS parsing, resulting in inconsistent display effects, mainly including the default style difference, box model calculation method, Flexbox and Grid layout support level, and inconsistent behavior of certain CSS attributes. 1. The default style processing is inconsistent. The solution is to use CSSReset or Normalize.css to unify the initial style; 2. The box model calculation method of the old version of IE is different. It is recommended to use box-sizing:border-box in a unified manner; 3. Flexbox and Grid perform differently in edge cases or in old versions. More tests and use Autoprefixer; 4. Some CSS attribute behaviors are inconsistent. CanIuse must be consulted and downgraded.

See all articles