Front End Testing
Components Architecture
Flux (Unidirectional Data Flow Architecture)

Presentational Components
- Are concerned with how things look.
- May contain both presentational and container components** inside, and usually have some DOM markup and styles of their own.
- Often allow containment via this.props.children.
- Have no dependencies on the rest of the app, such as Flux actions or stores.
- Don’t specify how the data is loaded or mutated.
- Receive data and callbacks exclusively via props.
- Rarely have their own state (when they do, it’s UI state rather than data).
PokemonCard
<template>
<div
class="flex flex-col mx-6 bg-blue rounded-lg py-4 px-8 w-32 h-32 my-6 cursor-pointer"
tid="pokemon-card"
>
<img class="w-16 h-16 rounded" :src="pokemon.url"/>
<p class="text-lg text-center">{{ pokemon.name }}</p>
</div>
</template>
<script>
export default {
name: 'PokemonCard',
props: ['pokemon'],
};
</script>
Concerns
- Receives props and renders well
- It doesn't care about who is using it.
- Doesn't know anything about Flux or Stores or Local Storage or whatever. It's full decoupled from application logic

Container Components
- Are concerned with how things work.
- May contain both presentational and container components inside but usually don’t have any DOM markup of their own except for some wrapping divs, and never have any styles.
- Provide the data and behavior to presentational or other container components.
- Call Flux actions and provide these as callbacks to the presentational components.
- Are often stateful, as they tend to serve as data sources.
PokemonList
<template>
<div class="container flex flex-row flex-wrap">
<template v-for="pokemon in pokemons">
<pokemon-card
:key="pokemon.name"
:pokemon="pokemon"
/>
</template>
</div>
</template>
<script>
import { mapActions, mapState } from 'vuex';
import PokemonCard from '@/components/PokemonCard.vue';
import store from '@/store';
export default {
name: 'PokeList',
components: { PokemonCard },
store,
computed: { ...mapState({ pokemons: (state) => state.pokemons }) },
methods: { ...mapActions(['getPokemons']) },
mounted: function () { return this.getPokemons() }
};
</script>Concerns
- Knows about the structure of the Flux Store.
- Orchestrate Presentational Components
- Executes application logic actions like fetching data

Decompose

Presentationals

Search Input
AmazonLogo

ShoppingCart

Product Card

Filters


OrderingDropdown
Containers



Header
Product Results
Pyramid of Testing

Unit Testing
Tests oriented towards checking the functionality of individual pieces of a software by verifying the results from that module are deterministic to a defined input.
Unit Tests !== Integration Tests
class Calculator
def sum(a, b)
a + b
end
def sub(a, b)
a - b
end
endclass TestCalculator
def test_sum
assert_equal calculator.sum(2, 2), 4
assert_equal calculator.sum(3, 5), 8
end
def test_substraction
assert_equal calculator.sub(4, 2), 2
assert_equal calculator.sub(10, 10), 0
assert_equal calculator.sub(10, 20), -10
end
endProduction Code
Testing Code
Complex Unit Testing / External Dependencies
class MailgunSender:
def initialize(api_key):
@api_key = api_key
@client = MailgunClient.new @api_key
end
def send(email):
response = @client.send build_payload(email)
if has_error? response
raise MailgunUnauthorized if unauthorized? response
raise MailgunBadFormat if bad_format? response
raise MailgunError
end
end
endUnit test should test small unit of code that could not be influenced by external modules at the moment of testing (libraries, HTTP Request, etc). This is required for tests to be Deterministic.
Testing
Example
class MailgunSenderTest
def test_sends_email
# Mocking phase
MailgunClient
.stubs(:send)
.returns(GOOD_RESPONSE)
mailgun_sender = MailgunSender.new 'fake-api-key'
assert_not_raises MailgunError do
mailgun_sender.send(EMAIL)
end
end
def test_unauthorized
MailgunClient
.stubs(:send)
.returns(UNAUTHORIZED_RESPONSE)
mailgun_sender = MailgunSender.new 'fake-api-key'
assert_raises MailgunUnauthorized do
mailgun_sender.send(EMAIL)
end
end
def test_bad_request
MailgunClient
.stubs(:send)
.returns(BAD_REQUEST_RESPONSE)
mailgun_sender = MailgunSender.new 'fake-api-key'
assert_raises MailgunBadRequest do
mailgun_sender.send(EMAIL)
end
end
endIntegration Tests
Tests oriented towards checking the functionality of compound pieces of software by verifying the results from the composition are deterministic to a defined input, taking into consideration external modules also.


The whole picture
Workshop time
Front End Testing
By Alberto Romero
Front End Testing
- 210