jfmengels / elm-review-test-values / NoTestValuesInProductionCode

rule : Configuration -> Review.Rule.Rule

Reports when functions or values meant to be used only in tests are used in production source code.

config =
    [ NoTestValuesInProductionCodeTest.rule
        (NoTestValuesInProductionCodeTest.startsWith "test_")

    -- or
    , NoTestValuesInProductionCodeTest.rule
        (NoTestValuesInProductionCodeTest.endsWith "_TESTS_ONLY")
    ]

This rule is meant to allow you to expose values from your module that you need for writing tests, while preserving the making sure they are not misused in production code. You can read about the problem and solution more in detail.

Fail

-- NoTestValuesInProductionCodeTest.startsWith "test_"
grantAdminRights user =
    { user | role = Role.test_admin }

-- NoTestValuesInProductionCodeTest.endsWith "_TESTS_ONLY"
grantAdminRights user =
    { user | role = Role.admin_TESTS_ONLY }

Success

-- module RoleTest exposing (roleTest)
roleTest =
    Test.describe "Role"
        [ Test.test "admins should be able to delete database " <|
            \() -> Expect.true (Role.canDeleteDatabase Role.test_admin)
        , Test.test "users should not be able to delete database " <|
            \() -> Expect.false (Role.canDeleteDatabase Role.user)
        ]

Values marked as test-only can be used in the declaration of other test values.

-- module User exposing (test_admin_user)
test_admin_user =
    { id = "001"
    , role = Role.test_admin
    }

When (not) to enable this rule

This rule is useful only if you have instances where you wish to add guarantees to the usage of your data types, but need to access internals in the context of your tests. Also, for this rule to work well, the naming convention for test-only values needs to be communicated to the rest of the team or project.

Try it out

You can try this rule out by running the following command:

elm-review --template jfmengels/elm-review-test-values/example --rules NoTestValuesInProductionCodeTest

The example uses the following configuration:

config =
    [ NoTestValuesInProductionCodeTest.rule
        (NoTestValuesInProductionCodeTest.startsWith "test_")
    ]


type Configuration

Configure how values should be tagged.

startsWith : String -> Configuration

A test-only value's name starts with the given string.

endsWith : String -> Configuration

A test-only value's name ends with the given string.