Can automatic module testing replace static type checking?

I began to study the whole idea of ​​unit testing and testing, and the more I think about it, the more it looks like a similar role for static type checking. Both methods provide runtime verification, quick response to certain types of errors in your program. However, correct me if I am mistaken, but it seems that the unit test package with full coverage will check all static type checks, and then some. Or formulated in another way, checks on a static type are only to “prove” that your program is correct, while unit tests will allow you to “prove” as much as you want (to a certain extent).

So, is there a reason to use a language with static type checking if you also use unit testing? A somewhat similar question was asked here , but I would like more detailed information. What specific benefits, if any, does the static type test for unit tests? Several questions come to mind, such as compiler optimization and intellisense, but are there any other solutions to these problems? Are there any other advantages / disadvantages that I have not thought about?

+4
source share
10 answers

I would think that automatic module testing would be important for dynamically typed languages, but that does not mean that it will replace the static type check in the context that you apply. In fact, some of those who use dynamic typing can actually use it because they don't want problems with constant type security checks.

The benefits of dynamically typed languages ​​are offered by more static typed languages ​​that go far beyond testing, and the type of security is just one aspect. The programming style and design differences across dynamic and static typed languages ​​are also very different.

In addition, unit tests that are written too vigorously for type safety mean that the software must not be dynamically typed in the end, or the design used must be written in a statically typed language, and not in a dynamic one.

+5
source

There is one indisputable fact about the quality of software.

If he cannot compile, he cannot send

In this rule, statically typed languages ​​will win dynamically typed languages.

Well, yes, this rule is not immutable. Web applications can be delivered without compilation (I deployed many test web applications that did not compile). But it’s fundamentally true that

The sooner you catch the error, the cheaper it is to fix it.

A statically typed language will prevent real errors at one of the earliest possible moments in the software development cycle. Dynamic language will not be. Unit testing, if you are the founder of a superhuman level, can replace a statically typed language.

But why bother? There are many incredibly smart people who write the whole error checking system for you in the form of a compiler. If you are worried about getting errors, rather use a statically typed language.

Please do not accept this message as a beating of dynamic languages. I use dynamic languages ​​every day and love them. They are incredibly expressive and flexible and allow you to incredibly love the program. However, in the event of an early error message, they lose statically typed languages.

+9
source

For any project with a reasonable size, you simply cannot take into account all situations with unit tests only.

So, my answer is “no,” and even if you manage to take into account all situations, you thereby defeated the whole purpose of using a dynamic language in the first place.

If you want to program a type of security, it is better to use a language with a type.

+6
source

Having coverage of 100% of the code does not mean that you have fully tested your application. Consider the following code:

if (qty > 3) { applyShippingDiscount(); } else { chargeFullAmountForShipping(); } 

I can get 100% code coverage if I pump qty = 1 and qty = 4.

Now imagine that my business condition was that "... for orders of 3 or more items, I must apply a discount on transportation costs ..". Then I will need to write tests that worked at the borders. So I would develop tests where qty was 2,3 and 4. I still have 100% coverage, but more importantly, I found an error in my logic.

And this is a problem that I only encounter with regard to code coverage. I think that in the best case you find yourself in a situation where the developer creates some initial tests based on business rules. Then, to increase the coverage number, they refer to their code when developing new test cases.

+3
source

Manifest typing (which I suppose you mean) is a form of specification, unit testing is much weaker because it gives only examples. An important difference is that the specification states what needs to be kept anyway, while the test covers only examples. You can never be sure that your tests cover all boundary conditions.

People also tend to forget the value of declared types as documentation. For example, if the Java method returns a List<String> , I immediately find out what I get, no need to read the documentation, test cases, or even the method code itself. Similarly for parameters: if a type is declared, I know what this method expects.

The value of the declaration of the type of local variables is much lower, since in well-written code the scope of the variable should be small. However, you can use static typing: instead of declaring a type that you allow the compiler to output it. Languages ​​like Scala or even C # let you do this.

Some testing styles come close to specification, for example. QuickCheck or Scala variant ScalaCheck generate tests based on specifications, trying to guess important boundaries.

+3
source

I suppose it could be if you are very solid. But why bother? If the language already checks the validity of static types, it would not make sense to test them (since you will get it for free).

Also, if you use static typed languages ​​with an IDE, the IDE can provide you with errors and warnings even before compiling for testing. I'm not sure if there are applications with automatic module testing that can do the same.

+1
source

I would say this in a different way - if you do not have a statically typed language, you should conduct very thorough unit tests if you plan to do something “real” with this code.

However, static typing (or rather explicit typing) has some significant advantages over unit tests, because of which I prefer it in general. It creates a much more understandable API and allows you to quickly view the "skeleton" of the application (i.e., the Input points to each module or section of code) in a way that is much more complicated with a dynamically typed language.

To summarize: in my opinion, with solid, rigorous unit tests, choosing between a dynamically typed language and a statically typed language is basically one of the tastes. Some prefer one; others prefer the other. Use the right tool for the job. But this does not mean that they are identical. Statically typed languages ​​will always have an advantage in certain directions, and languages ​​with dynamic input will always have an advantage in different ways. Unit tests are important to minimize the disadvantages of dynamically typed languages, but they do not completely eliminate them.

+1
source

No.

But this is not the most important question, the most important question: does it matter that he cannot?

Consider the purpose of checking a static type: to avoid a class of code defects (errors). However, this needs to be weighted in the context of a wider area of ​​all code defects. The most important thing is not a narrow tape comparison, but a comparison of the depth and breadth of the quality of the code, the simplicity of writing the right code, etc. If you can come up with a style / development process that allows your team to produce higher quality code more efficiently without checking the static type, then it's worth it. This is true even if you have holes in testing that will check static types.

+1
source

Given all the benefits of dynamic, late-binding languages, I suggest that one of the meanings offered by Unit Tests. You still need to carefully and deliberately encode the code, but this is requirement # 1 for any type of encoding IMHO. The ability to write clear and simple tests helps prove the clarity and simplicity of your design and your implementation. It also provides useful hints for those who see your code later. But I do not think that I will count on this to detect inconsistent types. But in practice, I do not find that type checking really catches a lot of real errors anyway. This is just not a mistake that I find in real code if you have a clear and simple coding style.

For javascript, I would expect jsLint to find almost all problems with type checking. primarily by offering alternative coding styles to reduce your exposure.

0
source

Type checking helps to conclude contracts between components in the system. Unit testing (as the name implies) checks the internal logic of the components.

For a single block of code, I think unit testing can really make static type checking unnecessary. But in a complex system, automatic tests cannot check all the multiplicity methods with which various components of the system can interact. For this, the use of interfaces (which, in a certain sense, is a kind of “contract” between components) becomes a useful tool to reduce potential errors. And interfaces require compilation type checking.

I really like programming in dynamic languages, so of course I don’t break dynamic typing. This is just a problem that I recently had. Unfortunately, I have no experience using a dynamic language for a large and complex system, so I would be interested to hear from other people whether this problem is real or just theoretical.

0
source

All Articles