Do all the things like ++ or -- rants, post your own rants, comment on others' rants and build your customized dev avatarSign Up
Lor-inc513984dfor n in range(3, 1000):
assert fib(n) = fib(n-1) + fib(n-2)
I would like to add to this, you should always test the behavior of logic and mathematics as well
assert true != false
assert 2 * 2 == 4
You never know when the laws of the universe suddenly stop working.
Oktokolo116283dThe most important property of unit test code is its maintainability, as the test itself isn't productive and has to be easy to read and alter. Most testing code also has to terminate in a reasonable time frame.
So simple checks for "f(a) results in b" are actually the best choice in most cases. They are pretty easy to read and maintain.
I would test a fibonacci function with inputs -1, 0, 1, 2, 3, 4, 10, 100, and the expected max input.
Normally, such known-result checks are done like:
for in, out in [
[-1, FailureVal], [0, FailureVal],
[1, 1], [2, 1], [3, 2]...
] do assertFunResult(f, in, out).
I have -1 and 0 in my example and assumed use of common native types - so the compiler will refuse to accept a float instead of an int.
That is best done by having generic test functions taking a function and testing it with various carefully (to get as much potential edge cases covered as possible) selected inputs of all types except the type it should accept. Fail when the tested function doesn't fail.
@Oktokolo This is why I often tell people that weakly typed languages require more work.
I've worked on a giant Haskell project (>10 million lines) and giant PHP project (>30 million lines).
The Haskell project has about 500 tests, and I would almost dare to claim that there are zero bugs. The PHP project has 160k tests, and to give you an idea of the amount of bugs... We pay $7500/m for Sentry.
Not saying every project should be written in Haskell... But I do believe strong(ish) type systems should be more common.
Zero bugs in non-trivial software - i doubt it.
But type systems indeed are there for a reason. Some actually are expressive enough to be used for specifying the type of acceptable data.
I would love to see a dynamically typed language with a decent type system - so you could have both: Hastily written prototypes and properly engineered libs written in the same language.
@Oktokolo Statically typed languages with good type inference get close to that ideal balance in my opinion -- Rust if you want to be on the safe side, Kotlin/Swift if you want things to be a bit easier.
These days, Rust is my default for both personal and work projects. I was actually very surprised how you can write very decent & safe Rust code with a basic subset of the the language -- It's not that difficult to write a program that can be read, understood, adjusted and compiled by a PHP junior.
@Oktokolo Depends on what you consider stable, but in general, I'd say it's quite stable since v1.0 was released in 2015.
You can't use unstable features on stable/beta channel, you have to use nightly and annotate your code with feature flags.
So for 99% of libraries you would add through Cargo, you can expect any abandoned package from 2015 to still work in a new project in 2025, unless the library specifically says it was made to use flagged features from nightly.
There should be no Py2/Py3 ecosystem splits.