Talking About TestingATT</>
JavaScript para QAs

Acerte 100% do quiz para continuar

Aula
Prévia gratuita

Tipos de dados

Os primitivos (undefined, null, Boolean, Number, String) e os tipos estruturais (Array, Object, Function) de que todo teste é feito.

Tudo em um teste é um pedaço de dado. O nome que você digita em um campo, o código de status que voltou, a lista de linhas de uma tabela, a resposta sim-ou-não para "esse botão está visível?".

O JavaScript organiza tudo isso em um pequeno número de tipos. Aprenda os tipos e a maioria das surpresas da linguagem deixa de ser surpresa.

Há duas famílias: os primitivos e os tipos estruturais.

Primitivos

Um primitivo é um valor único e simples. São cinco que você vai usar o tempo todo.

String

Texto. Escrito entre aspas simples, aspas duplas ou crases.

console.log('Acme Corporation')
console.log("Acme Corporation")

Escolha um estilo de aspas e mantenha a consistência. Este curso usa aspas simples.

Number

Qualquer número. O JavaScript não separa inteiros de decimais: 42 e 3.14 são ambos apenas Number.

console.log(200)
console.log(19.99)
👨‍🏫 É por isso que um código de status e um preço são do mesmo tipo. Isso também significa que 0.1 + 0.2 te dá 0.30000000000000004, o que não é um bug do JavaScript, e sim como computadores guardam decimais em toda parte. Nunca verifique o resultado exato de uma conta com decimais.

Boolean

Exatamente dois valores possíveis: true e false. É o tipo que toda asserção produz no fim das contas.

console.log(true)
console.log(false)

undefined

O valor de algo que existe mas nunca recebeu valor. O JavaScript atribui isso por você.

let statusCode
console.log(statusCode)

Isso imprime undefined. Ninguém definiu nada.

null

O valor de algo deliberadamente definido como "nada". A diferença para undefined importa: undefined significa "ninguém preencheu isso", null significa "alguém preencheu isso com nada".

const middleName = null
console.log(middleName)
👨‍🏫 Em uma resposta de API, "phone": null significa que o campo existe e o cliente não tem telefone. Uma chave phone ausente te dá undefined, ou seja, a API nem enviou o campo. São dois bugs diferentes, então vale saber distingui-los.

Tipos estruturais

Um tipo estrutural guarda vários valores, em uma estrutura. São três de que você precisa.

Array

Uma lista ordenada. Escrita com colchetes, itens separados por vírgula. A ordem é preservada, e as posições são numeradas a partir do zero.

const sizes = ['Small', 'Medium', 'Large']

console.log(sizes[0])
console.log(sizes[2])
console.log(sizes.length)

Isso imprime Small, depois Large, depois 3.

👨‍🏫 Contar a partir do zero confunde todo mundo no começo. O primeiro item está no índice 0, então o último item de um array de três itens está no índice 2, nunca no 3. Pedir sizes[3] te dá undefined.

Um array pode guardar qualquer coisa, inclusive outros arrays e objetos. Em testes, um array costuma ser uma lista de linhas, uma lista de entradas ou uma lista de valores esperados.

Object

Uma coleção de valores nomeados. Escrita com chaves, em pares chave: valor.

const customer = {
  name: 'Acme Corporation',
  size: 'Large',
  active: true,
}

console.log(customer.name)
console.log(customer.active)

Isso imprime Acme Corporation, depois true.

Um objeto é a cara do corpo de uma resposta de API, e a cara de um dado de teste. Arrays e objetos se aninham livremente: um array de objetos de cliente é o formato mais comum que você vai encontrar.

const customers = [
  { name: 'Acme Corporation', size: 'Large' },
  { name: 'Globex', size: 'Small' },
]

console.log(customers[1].name)

Isso imprime Globex.

Function

Um bloco de código reutilizável. No JavaScript, uma função é um valor como qualquer outro, e é por isso que ela está nesta lista em vez de em um capítulo à parte.

function greet(name) {
  return 'Olá, ' + name
}

console.log(greet('Walmyr'))

Isso imprime Olá, Walmyr.

👨‍🏫 O fato de uma função ser um valor é a ideia mais importante deste curso. É o que permite passar uma função para o it(), para o beforeEach() e para o forEach(). A lição 7 cobre funções direito.

Como checar um tipo

typeof te diz de que tipo é um valor.

console.log(typeof 'Acme')
console.log(typeof 42)
console.log(typeof true)
console.log(typeof undefined)
console.log(typeof { name: 'Acme' })
console.log(typeof [1, 2, 3])
console.log(typeof null)

Os dois últimos merecem atenção. typeof [1, 2, 3] responde 'object', não 'array', e typeof null também responde 'object', o que é um erro famoso da linguagem que nunca poderá ser corrigido sem quebrar a web.

Para checar se algo é um array, use Array.isArray().

console.log(Array.isArray([1, 2, 3]))
console.log(Array.isArray({ name: 'Acme' }))

Isso imprime true, depois false.

Visão geral da sintaxe 📖

typeof

Devolve uma string com o nome do tipo de um valor.

typeof 'Acme'

Array.isArray()

Devolve true quando o valor é um array. O jeito confiável de checar, já que o typeof não dá conta.

Array.isArray(['Small', 'Large'])

.length

A quantidade de itens de um array, ou de caracteres de uma string.

['a', 'b', 'c'].length
'Acme'.length

Acessando valores

Colchetes e um número para arrays, ponto e um nome para objetos.

sizes[0]
customer.name

A parte de testes 🧪

Tipos não são assunto acadêmico. Aqui está o falso positivo mais comum da automação de testes web, e ele é um problema de tipos.

Texto lido de uma página web é sempre uma String, mesmo quando parece um número.

it('mostra o total certo', () => {
  cy.get('[data-testid="total"]').invoke('text').then((total) => {
    // total é a string '42', não o número 42
    expect(Number(total)).to.equal(42)
  })
})

Sem aquela conversão com Number(), comparar '42' com 42 de forma estrita falha, e compará-los de forma frouxa passa por razões que você não pretendia. A lição 4 cobre exatamente essa diferença.

O segundo lugar em que tipos importam é o teste de API, onde saber o tipo esperado é o teste.

it('devolve um cliente bem formado', async ({ request }) => {
  const response = await request.get('/api/customers/1')
  const customer = await response.json()

  expect(typeof customer.name).toBe('string')
  expect(typeof customer.active).toBe('boolean')
  expect(Array.isArray(customer.contacts)).toBe(true)
})

Esse teste não se importa com o nome do cliente. Ele se importa que name seja texto, active seja um verdadeiro-ou-falso e contacts seja uma lista. Se uma mudança no backend transformar active na string 'true', todas as verificações de interface podem continuar passando, enquanto essa pega o problema na hora.

👨‍🏫 Um campo que muda de tipo é um dos bugs mais desagradáveis de encontrar depois, porque o valor continua parecendo certo quando você o imprime. 'true' e true são impressos de forma idêntica.

Conteúdo sugerido 📚

Exercício 🎯

Crie o 01-data-types.js no seu fork e faça o seguinte:

  1. Declare um valor de cada tipo primitivo: uma string, um número, um booleano, um undefined e um null
  2. Declare um array com pelo menos três strings e imprima o tamanho dele e o primeiro item
  3. Declare um objeto descrevendo um cliente, com nome, porte e se está ativo, e imprima dois dos campos
  4. Imprima o typeof de cada um dos seus cinco primitivos
  5. Imprima Array.isArray() tanto para o seu array quanto para o seu objeto

Rode com node 01-data-types.js, faça o commit e envie.

🙊 Aqui está uma forma de escrever:
const name = 'Acme Corporation'
const employees = 240
const active = true
let notSetYet
const phone = null

const sizes = ['Small', 'Medium', 'Large']
const customer = { name: 'Acme Corporation', size: 'Large', active: true }

console.log(sizes.length)
console.log(sizes[0])
console.log(customer.name, customer.active)

console.log(typeof name, typeof employees, typeof active, typeof notSetYet, typeof phone)
console.log(Array.isArray(sizes), Array.isArray(customer))
Duas coisas para reparar na saída.

typeof notSetYet imprime undefined mesmo sem nada ter sido atribuído. É o JavaScript preenchendo a lacuna, não um erro.

typeof phone imprime object, não null. É o erro da linguagem mencionado acima. Quando precisar checar por null, compare diretamente com ele em vez de confiar no typeof.

Mostre ao mundo o que você aprendeu 🌎

Para mostrar à sua rede profissional o que você aprendeu nesta lição, publique o seguinte no LinkedIn.

Comecei o curso "JavaScript para QAs" do @Walmyr Lima e Silva Filho na @Talking About Testing School, e a primeira lição já explicou um falso positivo que eu já tinha visto: texto lido de uma página é sempre uma string, mesmo quando parece um número, então compará-lo com um número não é a verificação que você acha que escreveu. #TalkingAboutTesting #TATSchool #JavaScriptForQAs #JavaScript #TestAutomation

👨‍🏫 Lembre-se de me marcar no seu post. Aqui está meu perfil no LinkedIn.

Quiz

Pergunta 1 de 2
Pontuação: 0

O que `typeof [1, 2, 3]` devolve, e o que você deveria usar no lugar?

Acerte 100% do quiz para continuar