objectionary / eo

EOLANG, an Experimental Pure Object-Oriented Programming Language Based on 𝜑-calculus
https://www.eolang.org
MIT License
1.01k stars 127 forks source link

No test - no run #34

Closed MadridianFox closed 3 years ago

MadridianFox commented 7 years ago

How about, mandatory testing? Objects have methods and every method must be tested. If at least one method has no test, compiler have a right throw a warning or even cancel compilation. Good test - that test which cover all possible cases. We can extract these cases from expected exceptions of inner objects and from special cases of method's arguments. Exceptions - the old song of OOP programming. But formal sign of special case for type - is something new. What you think about this?

gukoff commented 7 years ago

Assuming that the language would be compiled, this could be a part of a build script, which would compile a program, run the tests afterwards and fail the build in case something goes wrong.

I think, green tests should be a requirement for the shipping, not for the compilation. Otherwise, a language lacks a lot of agility.

pchmielowski commented 7 years ago

Maybe it should raise a warning, not an error. However it would be good to keep the "treat warnings as error" compiler options enabled by default.

mdbs99 commented 7 years ago

How the compiler will know that a program is a tester and other is the real program? How the compiler will know that a test method doesn't need a test to test the test? :)

MadridianFox commented 7 years ago

@mdbs99 We don't have tester program. Compiler is a tester. And test is not same object or method as in program. Test is an attribute of object like metadata in Clojure objects. Compiler may not testing code by default, but it should raise warning if any method of object hasn't test for at least one special case.

Eg, if method accept an integer, we must to test his behavior with positive, negative number, with zero, max_int and min_int. If we don't wrote test for zero, we can't be sure in our program. But if argument can't be a zero, it's not an integer.

mdbs99 commented 7 years ago

@MadridianFox I can't understand how this will work. Could you write an example using the EO syntax? (just imagine)

MadridianFox commented 7 years ago

I think what I gone too far with testing of all cases. It's may be impossible to find all use cases of object by arguments. But remained yet one criteria of better code - fact of existence of test for code.

nqafield commented 7 years ago

It seems very opinionated for the language/compiler to require unit tests. (I could also imagine people getting into the habit of writing a bunch of probably pointless tests just to keep the compiler happy.) Encouraging and facilitating unit testing is a different thing altogether of course. I guess I'll be interested to hear what Yegor thinks. He's not one to shy away from being opinionated (which is all good in my book). But at the moment I think this is a step too far.

MadridianFox commented 7 years ago

@pa9ey Yes, newbie can make empty tests for compiler satisfaction, but serious developer knows, that code without test is dead. It's not maintainable. We all start with wrong philosophy. When we learn to program, we want to write code. We interested to write code, but not to make functionality. And when we already have the skill, destiny force us make test of code. It should be other way around. We should to want not write code, we must be willing to formalize specs and satisfy these by writing code.

DronMDF commented 7 years ago

How compiler understand for test needed? In some cases test is not posible.

Run tests in compile and require test succes is good idea.

Question in other. :) Test is a good object? How to write tests?

MadridianFox commented 7 years ago

@DronMDF What is test? It is a specification of object's behavior. In some cases, we need not only describing of inputs and output of method. We need some computation for prove accordance object to spec. But all we need, it's to instantiate object and invoke his method. All other work may be done in other context - in context of compiler. We can to embed any other language in compiler for testing. It may be YAML for simple testing. JS/Python/Clojure for complex. It may be and EOlang, but it will be runned by compiler as test instructions and not be tested.

monsieurluge commented 7 years ago

I'm ok with those who say that only the complex behaviors need unit tests. The other object's behaviors, if written in a concise and strongly typed way, doesn't need tests.

The compiler must launch the already written tests, but i think that it must not require from the devs a 100% code coverage.

yegor256 commented 7 years ago

@MadridianFox I like the idea, a lot. I actually mentioned in the original prototype the necessity for the language/platform to support TDD. Not unit testing, but TDD. @pa9ey is right that just requiring tests to exist is not a good idea, because will lead to a lot of placeholders with no real meaning. We need to find a way to encourage coders to use TDD: tests go first, implementation next. Ideas?

MadridianFox commented 7 years ago

@yegor256 Unfortunately, we can't to forbid have code without test. There are "old" java libraries and some code with side effects. We need to have an mark for non-testable code, but it give to user way to violate testing policy. It irresistibly.

yegor256 commented 7 years ago

@MadridianFox what if allow people to share objects only through objectionary (#22) and will accept there only objects with certain level of test coverage?

MadridianFox commented 7 years ago

@yegor256 Terrible thought! Monopolistic repository tying the hands. It may be repository by default, but people should be able to work in closed web or even without it. We already have some public repositories, where we can to mark level of testing coverage. People already trusted to projects, which have good badges =)

gukoff commented 7 years ago

Quick thought - objects, which satisfy tests just like they implement types. Methods, accepting objects, which satisfy specific tests. Which implies global tests associated with types, not with objects.

In order to inspire people to use TDD, one shouldn't be restrictive. One should smooth the way to it and make TDD easy and pleasurable to use.

Assuming that every object declaration(= type implementation) would be global, I'd like to see tests right there, after the methods and attributes. Also an environment which could run the tests out of the box. Then everything a developer should do is to write a test. Not to configure anything, not even to create a separate file. Also, such kind of isolated object testing inevitably leads to the dummy objects - transparent type implementations, whose exact behaviour would be described in constructor. Perhaps, they should be implicit or/and an explicit part of a type declaration.

Tertioptus commented 7 years ago

Think Intention Driven Design or Documentation Driven Design.

One thing I hate about the modern English language is how much it has given way to bloat. For instance, using the word "conflate" has become trendy, when it holds no special attribution over "merge". That's ambiguity, and thus bloat. Who cares if you have a strong vocabulary, if all the words you know mean the same thing. Does it really aid your articulation?

My point! Well, just as the purity of a spoken language should be preserved, so should an object domain where every object has a unique purpose.

If every object has a unique purpose, it should only exist as a child part of a composite object, or a front-end object that addresses a user requirement.

Every requirement should be documented.

So if we standardize requirement documents, such that they live with the code and contain hooks to real objects. You should end up with %100 code coverage, because the intention of every object in the application must be described somewhere.

This doesn't even have to be as clunky as tools like JBehave, Cucumber, etc. But a compiler could start with a Latex or Markdown document and test the objects, with examples, cited within them. And then test any Type level EO docs if available as it traverses down the object tree. (As I've come to believe that if anything, JavaDocs of classes should contain examples of how to use the class, rather than how the class does it's job)

This way you naturally force documentation and code coverage. The code should never describe more than the documentation and vice versa.

Tertioptus commented 7 years ago

Class level JavaDocs should have unit tests in them!

This occurred to me as I was blabbering in my previous post.

Unit tests described in a Class JavaDoc would require a dependence on a fake object. Yet fake objects should be apart of the source folder, and tagged for the build manager to ignore. So I don't really see a problem with the dependence.

Also Yegor and I may disagree on this. But some mocking capability would be advantageous in such a case.

Example:


********
* A Number type that represents the maximum value between two numbers
*
* examples: 
* Number maxPrimary = Max.create(3,2), 
* Number maxFakeTwoNumbers = Max.create(FakeTwoNumbers.create(3,2)),
* Number maxAnonymousTwoNumbers = Max.create(TwoNumbers.create(){num1() returns 3;  num2() returns 2},
* Number maxMockedTwoNumbers = Max,create(mockTwoNumbers)
* where mockTwoNumbers.num1() returns 3 and mockTwoNumbers.num2 returns 2,
* assert no exceptions are thrown
*******
class Max implements Number
    Max(twoNumbers)
          Max(twoNumbers.num1, twoNumbers.num2)
    Max(num1, num2)

     ********
    * Returns the maximum value of contents
    *
    * example : 
    * Let's assertThat maxPrimary.value() == 3 and
    * maxFakeTwoNumbers.value() == 3,
    * etc
    *******
    integer value()
       return Predicate<integer>.create(
                     {
                     num1>num2 : num1,
                     num2>=num2 : num2
                    });
gukoff commented 7 years ago

@Tertioptus isn't this what you're talking about?

  1. http://legacy.python.org/dev/peps/pep-0316/
  2. https://docs.python.org/3/library/doctest.html
Tertioptus commented 7 years ago

@gukoff Yes, thank you! programming by contract. I think EO could do it even better.

Plus your IDE could automatically run the test while the Class/Type is being written. Such that when the objects behavior is fully implemented, the test lines go from red to green. Kind of a dynamic TDD. Which would be very satisfying, and reward both documentation and testing efforts immediately.

terales commented 7 years ago

Maybe a documentation tests concept from Rust can be helpful:

yegor256 commented 3 years ago

@MadridianFox it was a good idea, but I decide to close it. We will have a traditional model: code+tests. The validation of test coverage will be done outside of language scope.

0crat commented 3 years ago

Job gh:cqfn/eo#34 is not assigned, can't get performer