Showing posts with label How-to. Show all posts
Showing posts with label How-to. Show all posts

Tuesday, April 4, 2023

Elixir tips #2 - Doctest

A "hidden" gem of Elixir is the fact that you can actually test your documentation: yeah, you got it! you can test your documentation! 

Elixir makes documentation a first-class citizen in the language: it means documentation should be easy to write and easy to read.

If you are new about how to write Elixir documentation here the link .

We can now go directly to the concrete example. 

Let's start by creating a new project just by typing mix new doctest_demo :



If you now navigate to the lib and test folders you will find the following modules lib/doctest_demo and test/doctest_demo_test.exs (as described from the above output):



Without any further action let's run mix test and analyze the output:



Interesting fact is the output of mix test command: 1 doctest, 1 test, 0 failure. 

What does it mean 1 doctest
If you have a close look to line number 3 of test/doctest_demo_test.exs you will see the magic happens: doctest Doctestemo

With that syntax the code contained in the @doc snippet have been tested. How does it work? 

from official documentation:

Every new test starts on a new line, with an iex> prefix. Multiline expressions can be used by prefixing subsequent lines with either ...> (recommended) or iex>.


The expected result should start the line after the iex> and ...> line(s) and be terminated by a newline.

To run doctests include them in an ExUnit case with a doctest macro

 


Amazing! Did you know about it? We are actually making sure our documentation does not go out of date. 

Let's change the result of hello function to worlds and analyze what happens:



Niceee! doctest feature recognized that documentation is not aligned anymore with the code and it has been reported as error.

If you want to know more about it and its syntax and features here the link to the official documentation, enjoy it!

Monday, July 27, 2020

Delphi tips and tricks: Unknown custom attribute

Hacking, Cyber, Blackandwhite, Crime, Security

RTTI attributes are a Delphi language feature that allows you to add metadata information
to types and type members (comparable to C# attributes or Java annotations, to be clear). 
By attributes, you can add metadata information in a declarative way. An attribute is depicted
by square brackets ([ ]) placed above the element it is used for, the attribute can be queried at runtime by using RTTI techniques and you take appropriate actions when you think they are required.

That is just a short introduction to Delphi RTTI Attributes and because it is not the central topic of this post, you can find more information about it here: http://docwiki.embarcadero.com/RADStudio/en/Attributes_(RTTI).

As for every Delphi construct you have to import it: put the unit in the uses section to use a specif class, interface, function and so on... This is not really true for Attributes!

Let's take a look at this code, a simple console application:



As you can see the [MyCustomAttribute] it's not declared anywhere ( and trust me it's not declared in the System.SysUtils unit).
So what happens if we try to build the project? Curious?
We are able to build it with success:

 


This because the compiler produces a warning and not an error around the situation just described (using Delphi 10.4):

[dcc32 Warning] Project1.dpr(15): W1074 Unknown custom attribute

In some cases, you might write an incorrect attribute name, or not import the unit
containing that attribute and this could have terrible consequences at run-time: at first you could think that the RTTI Attribute is not working, the framework is not working and so on... but the real fact is that we didn't include the right unit or wrote an incorrect name and probably we didn't have a look to warnings. 

How can we be sure to have an error instead of a warning?

Up to Delphi 102, if you used a custom attribute that was not known to the compiler (because you typed it incorrectly or a unit was missing in the uses statement), you'd receive the warning:

Warning: W1025 Unsupported language feature: 'custom attribute'

The only way to turn it into an error was to set the Unsupported language feature to error. You had to go to Project | Options | Delphi Compiler | Hint and warnings | Unsupported Language Feature and set the value to error. From now on, every Unsupported language feature generates a compiler error. but that could have included also other unwanted scenarios.

Starting with 10.3, the same code will trigger a new specific warning as we have seen in the messages of the example project above:

Warning: W1074 Unknown custom attribute

Then now it is easier to turn this warning into an error by using the directive:

{$WARN UNKNOWN_CUSTOM_ATTRIBUTE ERROR}

If you add the above line in the previous project and try to build it again you will receive this error and the build will fail:


This is a really nice tip to know as it can save you a lot of time around troubleshooting, just because you didn't have a look to warnings after you write an incorrect attribute name, or not import the unit
containing that attribute. I saw so many times developers in forums and OS projects complaining about the behavior of a framework/feature when the real "mistake" was in a missed unit or misspelled name.