Ajout de nouvelles classes de tests
This commit is contained in:
parent
fe0e5804a3
commit
bb10b39b60
82
README.md
82
README.md
|
@ -1,6 +1,6 @@
|
||||||
Il s'agit d'un ensemble de scripts, de type "tests unitaires" permettant de valider le comportement d'un service web, du point de vue d'un client web.
|
Il s'agit d'un ensemble de scripts, de type "tests unitaires" permettant de valider le comportement d'un service web, du point de vue d'un client web.
|
||||||
|
|
||||||
## Installation
|
# Installation
|
||||||
|
|
||||||
Au minimum il faut Ruby pour l'exécution des scripts.
|
Au minimum il faut Ruby pour l'exécution des scripts.
|
||||||
|
|
||||||
|
@ -17,9 +17,9 @@ Une fois Ruby installé, depuis le dossier du projet :
|
||||||
|
|
||||||
Ça va installer localement des paquets Ruby nécessaires.
|
Ça va installer localement des paquets Ruby nécessaires.
|
||||||
|
|
||||||
## Exécution
|
# Exécution
|
||||||
|
|
||||||
### Partie "sécurité" :
|
## Partie "sécurité" :
|
||||||
|
|
||||||
bundle exec ruby -Itest test/secrity_test.rb
|
bundle exec ruby -Itest test/secrity_test.rb
|
||||||
|
|
||||||
|
@ -27,34 +27,94 @@ Il est possible d'utiliser un certificat SSL racine stocké en local (`test/cert
|
||||||
|
|
||||||
Il est possible d'utiliser un binaire `open_ssl` personnalisé, géré dans la méthode `openssl_path`.
|
Il est possible d'utiliser un binaire `open_ssl` personnalisé, géré dans la méthode `openssl_path`.
|
||||||
|
|
||||||
#### `test_certificate_level`
|
### `test_certificate_level`
|
||||||
|
|
||||||
Permet de vérifier la conformité avec un des niveaux normalisés proposés par Mozilla (https://wiki.mozilla.org/Security/Server_Side_TLS)
|
Permet de vérifier la conformité avec un des niveaux normalisés proposés par Mozilla (https://wiki.mozilla.org/Security/Server_Side_TLS)
|
||||||
|
|
||||||
#### `test_certificate`
|
### `test_certificate`
|
||||||
|
|
||||||
Vérifie la validité du certificat
|
Vérifie la validité du certificat
|
||||||
|
|
||||||
#### `test_accepts_tls_v1`
|
### `test_accepts_tls_v1`
|
||||||
|
|
||||||
Vérifie que le serveur accepte bien des connexions TLS v1
|
Vérifie que le serveur accepte bien des connexions TLS v1
|
||||||
|
|
||||||
#### `test_refuse_ssl_v3`
|
### `test_refuse_ssl_v3`
|
||||||
|
|
||||||
Vérifie que le serveur refuse bien des connexions SSL v3
|
Vérifie que le serveur refuse bien des connexions SSL v3
|
||||||
|
|
||||||
#### `test_hsts_header`
|
### `test_hsts_header`
|
||||||
|
|
||||||
Vérifie la présence de l'en-tête HTTP `HTTP-Strict-Transport-Security`.
|
Vérifie la présence de l'en-tête HTTP `HTTP-Strict-Transport-Security`.
|
||||||
|
|
||||||
### Partie "redirections" :
|
## Partie "redirections" :
|
||||||
|
|
||||||
bundle exec ruby -Itest test/domain_redirects_test.rb
|
bundle exec ruby -Itest test/domain_redirects_test.rb
|
||||||
|
|
||||||
#### `test_redirections`
|
### `test_redirections`
|
||||||
|
|
||||||
Vérifie que les redirections attendues aient bien lieu.
|
Vérifie que les redirections attendues aient bien lieu.
|
||||||
|
|
||||||
#### `test_http_codes`
|
### `test_http_codes`
|
||||||
|
|
||||||
Vérifie que les codes HTTP attendus soient bien reçus.
|
Vérifie que les codes HTTP attendus soient bien reçus.
|
||||||
|
|
||||||
|
## Partie "assets accessibility"
|
||||||
|
|
||||||
|
bundle exec ruby -Itest test/assets_accessibility_test.rb
|
||||||
|
|
||||||
|
### `test_rss_feeds`
|
||||||
|
|
||||||
|
Vérifie la présence de flux RSS sur la page et leur fonctionnement.
|
||||||
|
|
||||||
|
### `test_head_stylelsheets`
|
||||||
|
|
||||||
|
Vérifie la présence de CSS, qu'elles sont bien accessibles, et que leurs en-têtes HTTP les rendent cachables.
|
||||||
|
|
||||||
|
### `test_head_scripts`
|
||||||
|
|
||||||
|
Vérifie la présence de JS, qu'ils sont bien accessibles, et que leurs en-têtes HTTP les rendent cachables.
|
||||||
|
|
||||||
|
### `test_images`
|
||||||
|
|
||||||
|
Vérifie que toutes images de la page sont bien accessibles et cachables.
|
||||||
|
|
||||||
|
### `test_https_src`
|
||||||
|
|
||||||
|
Vérifie que toutes les balises avec attribut `src` sont bien en HTTPS.
|
||||||
|
|
||||||
|
### `test_cors`
|
||||||
|
|
||||||
|
Vérifie les en-têtes CORS sur la feuille de style et toutes les polices web qu'elle référence.
|
||||||
|
|
||||||
|
## Partie "cookies"
|
||||||
|
|
||||||
|
bundle exec ruby -Itest test/cookies_test.rb
|
||||||
|
|
||||||
|
`test_no_session_on_pages`
|
||||||
|
|
||||||
|
Vérifie que certaines pages ne poussent pas de cookies.
|
||||||
|
|
||||||
|
`test_session_on_pages`
|
||||||
|
|
||||||
|
Vérifie que certaines pages poussent bien un cookie.
|
||||||
|
|
||||||
|
## Partie "cache HTTP"
|
||||||
|
|
||||||
|
bundle exec ruby -Itest test/http_cache_test.rb
|
||||||
|
|
||||||
|
`test_varnish_hit`
|
||||||
|
|
||||||
|
Vérifie que certaines pages sont bien servies puis mises en cache par Varnish.
|
||||||
|
|
||||||
|
`test_homepage_first_visit`
|
||||||
|
|
||||||
|
Vérifie que certaines pages ont des en-têtes corrects pour le cache public.
|
||||||
|
|
||||||
|
`test_homepage_second_visit`
|
||||||
|
|
||||||
|
Vérifie que certaines pages rechargées en transmettant les infos de cache reçoivent une réponse "304".
|
||||||
|
|
||||||
|
`test_login_first_visit`
|
||||||
|
|
||||||
|
Vérifie que certaines pages ne soient pas mises en cache.
|
||||||
|
|
110
test/assets_accessibility_test.rb
Normal file
110
test/assets_accessibility_test.rb
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
require 'test_helper'
|
||||||
|
require "mechanize"
|
||||||
|
require "nokogiri"
|
||||||
|
|
||||||
|
class AssetsAccessibilityTest < Minitest::Test
|
||||||
|
include WebserverHelper
|
||||||
|
|
||||||
|
def test_rss_feeds
|
||||||
|
on_home_page do |page, doc|
|
||||||
|
feeds = doc.search("//head/link[@type='application/rss+xml']")
|
||||||
|
|
||||||
|
# Il y a au moins 1 flux RSS
|
||||||
|
assert feeds.size >= 1, "Expected to find an RSS feed"
|
||||||
|
|
||||||
|
feeds.each do |feed|
|
||||||
|
url = feed["href"]
|
||||||
|
assert_status_ok agent.get(url), "for #{url}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_head_stylelsheets
|
||||||
|
on_home_page do |page, doc|
|
||||||
|
stylesheets = doc.search("//head/link[@rel='stylesheet']")
|
||||||
|
|
||||||
|
# Il y a au moins 1 CSS "application"
|
||||||
|
assert stylesheets.any? { |stylesheet|
|
||||||
|
path = URI.parse(stylesheet["href"]).path
|
||||||
|
%r(\A/assets/application-\w+\.css\Z) =~ path
|
||||||
|
}, "Expected to find the application CSS"
|
||||||
|
|
||||||
|
# Tous les CSS sont accessibles et correctement configurés
|
||||||
|
stylesheets.each do |stylesheet|
|
||||||
|
url = stylesheet["href"]
|
||||||
|
if internal_url?(url)
|
||||||
|
assert_cachable_asset agent.get(url), "for #{url}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_head_scripts
|
||||||
|
on_home_page do |page, doc|
|
||||||
|
scripts = doc.search("//head/script[@src]")
|
||||||
|
|
||||||
|
# Il y a au moins 1 JS "application"
|
||||||
|
assert scripts.any? { |script|
|
||||||
|
path = URI.parse(script["src"]).path
|
||||||
|
%r|\A/assets/application-\w+\.js\Z| =~ path
|
||||||
|
}, "Expected to find the application JS"
|
||||||
|
|
||||||
|
# Tous les scripts externes sont accessibles
|
||||||
|
scripts.each do |script|
|
||||||
|
url = script["src"]
|
||||||
|
if internal_url?(url)
|
||||||
|
assert_cachable_asset agent.get(url), "for #{url}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_images
|
||||||
|
on_home_page do |page, doc|
|
||||||
|
doc.search("body img").each do |image|
|
||||||
|
url = image["src"]
|
||||||
|
if internal_url?(url)
|
||||||
|
assert_cachable_asset agent.get(url), "for #{url}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_https_src
|
||||||
|
on_home_page do |page, doc|
|
||||||
|
doc.search("[src]").each do |element|
|
||||||
|
assert_scheme "https", element["src"], "on page #{page.uri}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_cors
|
||||||
|
on_home_page do |page, doc|
|
||||||
|
stylesheets = doc.search("//head/link[@rel='stylesheet']")
|
||||||
|
|
||||||
|
# On récupère la feuille de style qui contient les appels aux polices web
|
||||||
|
vendor_stylesheet = stylesheets.detect { |stylesheet|
|
||||||
|
path = URI.parse(stylesheet["href"]).path
|
||||||
|
%r(\A/assets/vendor_bootstrap-\w+\.css\Z) =~ path
|
||||||
|
}
|
||||||
|
refute_nil vendor_stylesheet, "Expected to find a \"vendor_bootstrap\" CSS file"
|
||||||
|
|
||||||
|
# On extrait toutes les URL de polices web
|
||||||
|
css_url = vendor_stylesheet["href"]
|
||||||
|
pattern = /url\((?:"|')?([^\)"']+)(?:"|')?\)/
|
||||||
|
font_urls = agent.get(css_url).body.scan(pattern).flatten
|
||||||
|
|
||||||
|
refute font_urls.empty?, "Expected to find webfonts in #{css_url}"
|
||||||
|
|
||||||
|
# On vérifie que les en-têtes sont présents
|
||||||
|
origin = "https://www.example.com/"
|
||||||
|
font_urls.each do |font_url|
|
||||||
|
page = agent.get(font_url, [], nil, { "Origin" => origin })
|
||||||
|
actual = header(page, "access-control-allow-origin")
|
||||||
|
|
||||||
|
assert_equal origin, actual, "Expected CORS header to match the request origin for #{font_url}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
47
test/cookies_test.rb
Normal file
47
test/cookies_test.rb
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
require 'test_helper'
|
||||||
|
require 'mechanize'
|
||||||
|
|
||||||
|
class CookiesTest < Minitest::Test
|
||||||
|
include WebserverHelper
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@agent = Mechanize.new { |a|
|
||||||
|
a.follow_redirect = false
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_no_session_on_pages
|
||||||
|
[
|
||||||
|
"/",
|
||||||
|
"/faq",
|
||||||
|
].each do |path|
|
||||||
|
url = "https://#{domain}#{path}"
|
||||||
|
page = @agent.get(url)
|
||||||
|
|
||||||
|
refute_has_session_cookie @agent, "_example_session", "for #{url}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_session_on_pages
|
||||||
|
[
|
||||||
|
"/login",
|
||||||
|
"/store",
|
||||||
|
].each do |path|
|
||||||
|
url = "https://#{domain}#{path}"
|
||||||
|
page = @agent.get(url)
|
||||||
|
|
||||||
|
assert_has_session_cookie @agent, "_example_session", "for #{url}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def assert_has_session_cookie(agent, cookie_name, context = nil)
|
||||||
|
message = message_with_context("Expected to find a session cookie named '#{cookie_name}'", context)
|
||||||
|
assert_includes agent.cookie_jar.map(&:name), cookie_name, message
|
||||||
|
end
|
||||||
|
|
||||||
|
def refute_has_session_cookie(agent, cookie_name, context = nil)
|
||||||
|
message = message_with_context("Expected to not find a session cookie named '#{cookie_name}'", context)
|
||||||
|
refute_includes agent.cookie_jar.map(&:name), cookie_name, message
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
93
test/http_cache_test.rb
Normal file
93
test/http_cache_test.rb
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
require 'test_helper'
|
||||||
|
require "mechanize"
|
||||||
|
|
||||||
|
class HTTPCacheTest < Minitest::Test
|
||||||
|
include WebserverHelper
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@agent = Mechanize.new { |a|
|
||||||
|
a.follow_redirect = false
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_varnish_hit
|
||||||
|
skip("Pas de test avec Varnish") if ENV["VARNISH"] == "0"
|
||||||
|
|
||||||
|
[
|
||||||
|
"https://#{domain}/",
|
||||||
|
].each do |url|
|
||||||
|
# Pour assurer la mise en cache par Varnish
|
||||||
|
page = @agent.get(url)
|
||||||
|
|
||||||
|
assert_has_header "x-varnish", page, "for #{url}"
|
||||||
|
assert_has_header "x-cache", page, "for #{url}"
|
||||||
|
|
||||||
|
# On laisse un peu de temps au cache pour se réchauffer
|
||||||
|
sleep(0.1)
|
||||||
|
|
||||||
|
# On refait la requête en espérant avoir un HIT
|
||||||
|
@agent.reset
|
||||||
|
page = @agent.get(url)
|
||||||
|
|
||||||
|
assert_x_cache_hit page, "for #{url}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_homepage_first_visit
|
||||||
|
[
|
||||||
|
"https://#{domain}/",
|
||||||
|
].each do |url|
|
||||||
|
page = @agent.get(url)
|
||||||
|
|
||||||
|
assert_status_ok page, "for #{url}"
|
||||||
|
assert_has_etag page, "for #{url}"
|
||||||
|
assert_has_last_modified page, "for #{url}"
|
||||||
|
# assert_max_age "300", page, "for #{url}"
|
||||||
|
# refute_must_revalidate page, "for #{url}"
|
||||||
|
assert_public page, "for #{url}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_homepage_second_visit
|
||||||
|
[
|
||||||
|
"https://#{domain}/",
|
||||||
|
].each do |url|
|
||||||
|
page1 = @agent.get(url)
|
||||||
|
assert_status_ok page1, "for #{url} on 1st visit"
|
||||||
|
|
||||||
|
if last_modified = last_modified_header(page1)
|
||||||
|
# il faut reinitialiser l'agent pour vider le cache et l'historique
|
||||||
|
@agent.reset
|
||||||
|
page2a = @agent.get(url, [], nil, {
|
||||||
|
"If-Modified-Since" => last_modified
|
||||||
|
})
|
||||||
|
assert_status_not_modified page2a, "for #{url} on 2nd visit with Last-Modified"
|
||||||
|
else
|
||||||
|
flunk "Expected to find a Last-Modified header for #{url} on 1st visit"
|
||||||
|
end
|
||||||
|
|
||||||
|
if etag = etag_header(page1)
|
||||||
|
# il faut reinitialiser l'agent pour vider le cache et l'historique
|
||||||
|
@agent.reset
|
||||||
|
page2b = @agent.get(url, [], nil, {
|
||||||
|
"If-None-Match" => etag_header(page1)
|
||||||
|
})
|
||||||
|
assert_status_not_modified page2b, "for #{url} on 2nd visit with ETag"
|
||||||
|
else
|
||||||
|
flunk "Expected to fin an ETag header for #{url} on 1st visit"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_login_first_visit
|
||||||
|
[
|
||||||
|
"https://#{domain}/login",
|
||||||
|
].each do |url|
|
||||||
|
page = @agent.get(url)
|
||||||
|
|
||||||
|
assert_max_age "0", page, "for #{url}"
|
||||||
|
assert_must_revalidate page, "for #{url}"
|
||||||
|
assert_private page, "for #{url}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue