Tools for JS Style Guidelines

Question
What are some useful tools for enforcing JavaScript style guidelines?

Answer
Two are JSLint and JSHint.

Comments
JSLint is a tool written by famed Douglas Crockford. It’s a tool that detects potential errors and stylistic concerns in your code. JSHint is a fork of JSLint, and it provides a less strict, more customizable experience. Both are excellent options, and integrating one or both into your development process is a great way to enforce JS code conventions. Additionally, Crockford has provided rules on JavaScript style in the following documents:
Part One deals with syntax and basic patterns.
Part Two deals with language idioms.
Code Conventions for the JavaScript Language contains points from the first two, with a small number of style guidelines.

Standard Libraries and Test Automation

Problem
You need to develop a suite of automated test cases for an application you own. You dig in and start writing all the functionality required to build up a robust test suite. Are you proceeding wisely?

Solution
As it turns out, no you’re not. There’s a good chance someone has already solved your problem or problems. It’s best to see if you can find the capabilities you desire in a third-party library.

Comments
Favor reusable libraries to make your solution simpler and clearer. An added benefit to this approach is well-tested code.

Coordinate-Based Clicks and Non-Standard Controls

Problem
You’re automating a test, and you need to work with a custom control. The tool you’re using doesn’t want to cooperate. Should you implement click actions using X and Y coordinates?

Solution
It’s wise to avoid implementing hard-coded clicks. Instead, use selectors to obtain a parent element and work your way down the DOM tree.

Comments
Why? Using coordinates will make your tests more brittle; especially when it comes to responsive applications.

Add Randomness to Automated Tests

Question
How should you automate cases that exercise functionality in a variety of ways?

Answer
Write several workflow-based functions or methods and randomly inject them in your tests.

Comments
It’s important to add an element of randomness in your automated tests. This holds true for both data and operations. For example, use data-driven techniques to switch up the data used by tests.

Example
The example below demonstrates a data-driven approach to testing a login feature.

import { t } from 'testcafe';

fixture `login`
    .page `www.example.com`;

const testCases = [
    {
        name:     'Valid User',
        email:    'valid@example.fake',
        password: 'pass'
    },
    {
        name:     'Invalid User',
        email:    'invalid@example.fake',
        password: 'fail'
    }
];

async function performLogin (email, password) {
    await t
        .typeText('#email', email)
        .typeText('#password', password)
        .click('#submit');
}

for (const user of testCases) {
    test('test ' + user.name, async t => {
        await performLogin(user.email, user.password);

        // Confirm valid user can login.
        await t.expect('#username').eql('Valid User');

        // Confirm invalid user can't login.
        ...
    });
}

Using Static Code Analyzers

Question
What can be done to check for common programming errors and standards violations in automation code?

Answer
Use static analysis tools to analyze the code. For example, jslint for the JavaScript language.

Comments
Static analysis tools help identify common syntax errors and standards violations. Some even raise warnings about poor programming style. For example, functions that are too long or take too many arguments.

Use Coding Standards for Test Code

Question
Should you adhere to coding standards when writing test automation code?

Answer
In short, yes. Follow coding standards for the language and technology used. Do this even if the quality of test automation code isn’t expected to be at the level of application code.

Example
The example below uses the fantastic tool TestCafe.

import { Selector } from 'testcafe';

fixture `example`
    .page `https://google.com`;

// Incorrect. An obscure way to name a selector.
const txtSearch = Selector('#q');

// Correct. Selectors have meaningful names.
const searchField = Selector('#q');
const pageTitle = Selector('title');

test('User can search Google', async t => {
    await t
        .typeText(searchField, 'Jason Riley')
        .expect(pageTitle.innerText).contains('Jason Riley');
});

Confirm All Options in Logical Conditions

Question
What should you do when you have automated scripts that contain assertions with many logical conditions?

Answer
Automated tests should not contain logic in them or many assertions, for that matter. But, if a test requires logic, be sure to check all conditions.

Comments
Consider using parentheses with logical expressions. It helps with code comprehension.

Validating Bit-Coded Enum Values

Question
What’s the recommended way to check bit-coded enum values?

Answer
The following code demonstrates how to test bit-coded enum values.

FileProperty fileProperty = GetFileProperties();

// Incorrect. This will fail if fileProperty has more than one bit set.
if ( fileProperty == FileProperty.Hidden ) {
    ...
}

// Also incorrect. This cannot test multiple bits at once.
if ( (fileProperty & FileProperty.Hidden ) != 0 ) {
    ...
}

// The correct way.
if ( (fileProperty & FileProperty.Hidden) == FileProperty.Hidden ) {
    ...
}

// An example that checks whether a file is System AND Hidden.
FileProperty property = FileProperty.System | FileProperty.Hidden;
if ( (fileProperty & property) == property ) {
    ...
}