From 4ae0c3749f668acd8202e5481cd7fb32a52ef6b4 Mon Sep 17 00:00:00 2001 From: Jeroen Engels Date: Tue, 23 Jul 2019 09:23:08 +0200 Subject: [PATCH] Add tips on how to write rules/tests --- src/Lint/Rule.elm | 32 +++++++++++++++++++++++++++----- src/Lint/Test.elm | 42 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/src/Lint/Rule.elm b/src/Lint/Rule.elm index 606d62cf..82c559d2 100644 --- a/src/Lint/Rule.elm +++ b/src/Lint/Rule.elm @@ -9,8 +9,6 @@ module Lint.Rule exposing {-| This module contains functions that are used for writing rules. -TODO Explain that and why people need to look at the documentation for elm-syntax. - # Definition @@ -22,10 +20,10 @@ TODO Explain that and why people need to look at the documentation for elm-synta ## How does it work? -`elm-lint` turns the code of the analyzed file into an [Abstract Syntax Tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree) -(AST) using the [elm-syntax`package](https://package.elm-lang.org/packages/stil4m/elm-syntax/latest/). +`elm-lint` turns the code of the analyzed file into an [Abstract Syntax Tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree) +using the [`elm-syntax` package](https://package.elm-lang.org/packages/stil4m/elm-syntax/latest/). An AST is a tree-like structure which represents your source code. -Then,`elm-lint\` will traverse the nodes in the AST in the following pre-defined +Then,`elm-lint` will traverse the nodes in the AST in the following pre-defined order, and call the visitor function associated to the type of node: - The module definition, visited by [`withSimpleModuleDefinitionVisitor`](#withSimpleModuleDefinitionVisitor) and [`withModuleDefinitionVisitor`](#withModuleDefinitionVisitor) @@ -43,11 +41,35 @@ Evaluating a node means two things: I recommend using the "simple with\*" visitors if you don't need to collect data, as they are simpler to use +`elm-lint` relies on the [`elm-syntax`package](https://package.elm-lang.org/packages/stil4m/elm-syntax/latest/), +and all the node types you'll see will be coming from there. You are likely to +need to have the documentation for that package open when writing a rule. + There are plenty of examples in the documentation for each visitor function, and you can also look at the source code for existing rules to better grasp how rules work. +## Tips on how to write a rule + +In the following section, you'll find all the functions needed to create a rule. +Here are a few tips on how to do that efficiently: + + +### Look at the documentation for [`elm-syntax`](https://package.elm-lang.org/packages/stil4m/elm-syntax/latest/) + +`elm-lint` is heavily dependent on the types that [`elm-syntax`](https://package.elm-lang.org/packages/stil4m/elm-syntax/latest/) +provides. If you don't understand the AST it provides, you will have a hard time +implementing the rule you wish to create. + + +### Use Test-Driven Development + +This package comes with [`Lint.Test`](./Lint-Test), which works with [`elm-test`](https://github.com/elm-explorations/test). +I recommend reading through [`the tips on testing`](./Lint-Test#tips-on-testing) before +starting writing a rule. + + ## Creating a linting rule @docs newSchema, fromSchema diff --git a/src/Lint/Test.elm b/src/Lint/Test.elm index 0a5a2514..14b8bfab 100644 --- a/src/Lint/Test.elm +++ b/src/Lint/Test.elm @@ -35,6 +35,40 @@ module Lint.Test exposing ] +# Tips on testing + + +## Use Test-Driven Development + +Writing a linting rules is a process that works really well with the Test-Driven +Development process loop, which is: + + - Before writing any code, write a failing test. + - Run the test and make sure that it is failing, otherwise you can't be + sure that the test is well-written. + - Write the simplest (almost stupid) code to make the test pass + - Run the tests again and make sure that the test is passing, and that you + didn't break any previous tests + - Optionally, refactor your code but be sure not to change the behavior of the + implementation. You should not support new things, as you want to write tests + for that first. + - (Then start over from step 1) + + +## What should you test? + +You should test the scenarii where you expect the rule to report something. At +the same time, you should also test when it shouldn't. I encourage writing tests +to make sure that things that are similar to what you want to report are not +reported. + +For instance, if you wish to report uses of variables named `foo`, write a test +that ensures that the use of variables named differently does not get reported. + +Tests are pretty cheap, and it is probably better to have too many tests rather +than too few tests. + + # Running tests @docs LintResult, run @@ -44,14 +78,6 @@ module Lint.Test exposing @docs ExpectedError, expectErrors, expectNoErrors, error, atExactly - -# Tips on testing - - -## What should you test? - -TODO Add helpful tips - -} import Array exposing (Array)