Préparation entretien · 227 questions

Questions d'entretien Java pour QA et SDET

Mis à jour

Java tel que les testeurs et SDET le rencontrent vraiment — OOP pour la conception de framework, collections pour les données de test, le piège == vs .equals(), exceptions et POJO — chacune avec la réponse courte à dire à voix haute, la relance, et l'erreur à éviter. Pas un bachotage Java générique ; Java à travers le prisme du test. Parcourez les aperçus ; ouvrez ce dont vous avez besoin.

16 questions

Quels sont les quatre piliers de l'OOP, et où apparaissent-ils dans un framework de test ?

OOP Javajuniormid

Encapsulation (regrouper les données avec les méthodes qui les protègent), héritage (un type réutilise le comportement d'un autre), polymorphisme (une interface, plusieurs implémentations),…

Encapsulation (regrouper les données avec les méthodes qui les protègent), héritage (un type réutilise le comportement d'un autre), polymorphisme (une interface, plusieurs implémentations), abstraction (exposer le quoi, cacher le comment).

L'avantage en entretien est de nommer où chacun vit dans l'automatisation : un Page Object encapsule ses locators ; un BasePage dont les autres héritent ; une interface de driver avec des implémentations Chrome/Firefox, c'est du polymorphisme ; et une abstraction comme LoginPage.login() qui cache les clics. Réciter des définitions, c'est junior ; les mapper à un framework, c'est la réponse SDET.

Points clés
  • Encapsulation, Héritage, Polymorphisme, Abstraction
  • Page Object = encapsulation ; BasePage = héritage
  • Interface de driver avec implémentations de navigateurs = polymorphisme
Ils demanderont ensuite · touchez-en un pour la réponse
Le piège

Se contenter de lister les quatre mots est une réponse junior. Les examinateurs attendent un exemple concret de chacun — idéalement tiré de code de test, puisque c'est le métier.

Copier le lien

Quelle est la différence entre == et .equals() en Java ?

Java essentieljuniormid

== compare les références — ces deux variables sont-elles exactement le même objet en mémoire. .equals() compare la valeur — ces deux objets signifient-ils la même chose, selon la définition de la…

== compare les références — ces deux variables sont-elles exactement le même objet en mémoire. .equals() compare la valeur — ces deux objets signifient-ils la même chose, selon la définition de la classe.

Pour les objets, == n'est presque jamais ce que vous voulez. Deux chaînes au texte identique peuvent être des objets différents, donc "abc" == new String("abc") est faux tandis que .equals() est vrai. C'est le bug Java le plus courant dans les assertions de test — comparer attendu et réel avec == et obtenir un faux échec.

Exemple concret

Un test comparait la chaîne de statut renvoyée par une API à « ACTIVE » avec == et était aléatoirement instable — parfois les chaînes étaient internées, parfois non. Passer à .equals() (ou mieux, une bibliothèque d'assertions) l'a corrigé définitivement.

Points clés
  • == compare les références (même objet ?) ; .equals() compare la valeur
  • Pour les objets/chaînes vous voulez presque toujours .equals()
  • == sur les chaînes est le faux échec classique dans les assertions de test
Ils demanderont ensuite · touchez-en un pour la réponse
Copier le lien

Surcharge (overloading) versus redéfinition (overriding) — quelle est la différence ?

OOP Javamid

La surcharge, c'est le même nom de méthode, des paramètres différents, dans la même classe — résolue à la compilation par les arguments que vous passez.

La surcharge, c'est le même nom de méthode, des paramètres différents, dans la même classe — résolue à la compilation par les arguments que vous passez. La redéfinition, c'est une sous-classe qui remplace la méthode d'un parent avec la même signature — résolue à l'exécution par le type réel de l'objet.

Dans un framework : un click(WebElement) et un click(By) sont des surcharges ; une méthode de BasePage qu'une page spécifique redéfinit est une redéfinition. Le signe que les examinateurs écoutent, c'est « compilation vs exécution » — c'est ce qui prouve que vous comprenez le mécanisme, pas juste les mots.

Points clés
  • Surcharge : même nom, params différents, même classe, à la compilation
  • Redéfinition : sous-classe remplace la méthode parente, même signature, à l'exécution
  • La surcharge est du polymorphisme à la compilation ; la redéfinition à l'exécution
Ils demanderont ensuite · touchez-en un pour la réponse
Copier le lien

Classe abstraite ou interface — quand utiliseriez-vous chacune ?

OOP Javamid

Une interface est un contrat — un ensemble de méthodes qu'un type promet de fournir ; une classe peut en implémenter plusieurs.

Une interface est un contrat — un ensemble de méthodes qu'un type promet de fournir ; une classe peut en implémenter plusieurs. Une classe abstraite est une base partielle — elle peut détenir un état partagé et des méthodes implémentées, et une classe n'en étend qu'une.

Règle générale : interface pour les capacités « peut faire ceci » à travers des types sans rapport (un Payable, un Reportable) ; classe abstraite pour « est une sorte de » avec du code partagé, comme un BasePage que toutes les pages étendent pour le driver et les attentes communs. Depuis Java 8 les interfaces peuvent avoir des méthodes par défaut, donc la frontière s'est brouillée — mais l'héritage simple vs multiple et l'état partagé la décident encore.

Points clés
  • Interface : contrat, plusieurs par classe, basée sur la capacité
  • Classe abstraite : base partielle avec état/code partagé, héritage simple
  • BasePage = classe abstraite ; une capacité transversale = interface
Ils demanderont ensuite · touchez-en un pour la réponse
Copier le lien

Pourquoi l'encapsulation compte-t-elle dans un Page Object ?

OOP Javamid

L'encapsulation veut dire que le Page Object possède ses locators de façon privée et n'expose que des méthodes au niveau de l'intention — login(user, pass), pas les champs bruts.

L'encapsulation veut dire que le Page Object possède ses locators de façon privée et n'expose que des méthodes au niveau de l'intention — login(user, pass), pas les champs bruts. Les tests appellent le comportement et ne touchent jamais un sélecteur.

C'est tout le gain : quand le markup du formulaire de connexion change, vous éditez un locator privé dans une classe, et chaque test qui se connecte continue de marcher sans y toucher. Exposez les locators publiquement et ils fuitent dans les tests, et un ajustement d'UI devient un changement de cinquante fichiers. L'encapsulation est ce qui rend un framework d'UI viable.

Points clés
  • Locators privés, méthodes au niveau intention publiques
  • Un changement d'UI touche une classe, pas chaque test
  • Des locators qui fuitent = une refonte devient une édition de masse
Ils demanderont ensuite · touchez-en un pour la réponse
Copier le lien

Pourquoi les chaînes Java sont-elles immuables, et quand utilisez-vous StringBuilder ?

Java essentielmid

Une String ne peut pas être changée après sa création — chaque « modification » crée un nouvel objet. Ça donne de la sûreté (les chaînes peuvent être partagées et mises en cache, les clés dans les…

Une String ne peut pas être changée après sa création — chaque « modification » crée un nouvel objet. Ça donne de la sûreté (les chaînes peuvent être partagées et mises en cache, les clés dans les maps restent stables) mais ça veut dire que construire une chaîne dans une boucle avec + crée un tas d'objets jetables.

Utilisez StringBuilder quand vous assemblez une chaîne morceau par morceau — concaténer dans une boucle, construire un locator dynamique ou une ligne de rapport. Pour une poignée de concaténations ça n'a pas d'importance ; dans une boucle c'est la différence entre un objet et des centaines.

Points clés
  • Les chaînes sont immuables — chaque changement crée un nouvel objet
  • L'immuabilité apporte la sûreté et des clés de map sûres
  • StringBuilder pour construire des chaînes dans une boucle
Ils demanderont ensuite · touchez-en un pour la réponse
Copier le lien

List, Set, Map — quelle est la différence et quand prenez-vous chacun ?

Collectionsjunior

Une List est une séquence ordonnée qui autorise les doublons — utilisez-la quand l'ordre compte ou que les éléments peuvent se répéter (une liste de lignes de test).

Une List est une séquence ordonnée qui autorise les doublons — utilisez-la quand l'ordre compte ou que les éléments peuvent se répéter (une liste de lignes de test). Un Set contient des éléments uniques, pas de doublons — utilisez-le pour dédupliquer ou vérifier l'appartenance (l'ensemble des IDs de produits visibles). Une Map, ce sont des paires clé-valeur — utilisez-la pour des recherches (une map de nom d'utilisateur vers rôle attendu).

La question derrière la question en automatisation : « j'ai récupéré ces valeurs, sont-elles toutes uniques ? », c'est un Set ; « quel est le prix pour ce SKU ? », c'est une Map ; « les lignes dans l'ordre », c'est une List.

Points clés
  • List : ordonnée, doublons autorisés
  • Set : éléments uniques, appartenance/déduplication
  • Map : recherches clé-valeur
Ils demanderont ensuite · touchez-en un pour la réponse
Copier le lien

ArrayList versus LinkedList — comment choisir ?

Collectionsmid

ArrayList est soutenue par un tableau redimensionnable — accès aléatoire rapide par index, insertions/suppressions plus lentes au milieu (elle décale les éléments).

ArrayList est soutenue par un tableau redimensionnable — accès aléatoire rapide par index, insertions/suppressions plus lentes au milieu (elle décale les éléments). LinkedList, ce sont des nœuds avec des pointeurs — insertions/suppressions rapides aux extrémités, mais accès par index lent car elle parcourt la chaîne.

Réponse honnête pour le code de test : utilisez ArrayList presque toujours. Vous itérez et indexez surtout dans des collections de données de test, ce qu'ArrayList fait le mieux, et les facteurs constants la favorisent. LinkedList ne gagne sa place qu'avec beaucoup d'ajouts/suppressions en tête — rare dans une suite de test.

Points clés
  • ArrayList : soutenue par tableau, accès aléatoire rapide, insertions au milieu lentes
  • LinkedList : basée sur des nœuds, insertions aux extrémités rapides, accès par index lent
  • Par défaut ArrayList pour les données de test — vous itérez et indexez surtout
Ils demanderont ensuite · touchez-en un pour la réponse
Copier le lien

Comment une HashMap fonctionne-t-elle en interne ?

Collectionsmidsenior

Elle stocke les entrées dans des buckets indexés par le hashCode de la clé. Put : hacher la clé pour trouver un bucket, et y stocker la clé-valeur.

Elle stocke les entrées dans des buckets indexés par le hashCode de la clé. Put : hacher la clé pour trouver un bucket, et y stocker la clé-valeur. Get : hacher la clé, aller droit au bucket, et utiliser equals() pour trouver l'entrée exacte. C'est pourquoi les recherches sont grosso modo en O(1).

Deux clés peuvent hacher vers le même bucket — une collision — donc un bucket contient plusieurs entrées (une liste, ou un arbre quand il devient long). C'est pourquoi le hashCode et equals d'une clé doivent s'accorder : rompez ce contrat et une clé que vous avez stockée devient introuvable, atterrissant dans un bucket et cherchée dans un autre.

Points clés
  • Clés hachées vers des buckets ; get/put sont ~O(1)
  • Les collisions partagent un bucket (liste/arbre d'entrées)
  • hashCode + equals doivent s'accorder sinon les clés se perdent
Ils demanderont ensuite · touchez-en un pour la réponse
Copier le lien

Exceptions vérifiées (checked) versus non vérifiées (unchecked) — quelle est la différence ?

Java essentielmid

Les exceptions vérifiées (IOException, InterruptedException) doivent être déclarées ou attrapées — le compilateur vous force à les gérer.

Les exceptions vérifiées (IOException, InterruptedException) doivent être déclarées ou attrapées — le compilateur vous force à les gérer. Les exceptions non vérifiées (NullPointerException, IllegalArgumentException) étendent RuntimeException et n'ont pas à être attrapées ; elles signalent des bugs.

En Selenium vous rencontrez les deux : NoSuchElementException est non vérifiée (un bug ou une mauvaise attente), tandis qu'InterruptedException de Thread.sleep est vérifiée et doit être gérée. L'intention de conception : vérifiée pour les conditions externes récupérables, non vérifiée pour les erreurs de programmation que vous devriez corriger plutôt qu'attraper.

Points clés
  • Vérifiée : le compilateur force la gestion (IOException)
  • Non vérifiée : famille RuntimeException, optionnelle (NullPointer)
  • Vérifiée = externe récupérable ; non vérifiée = un bug à corriger
Ils demanderont ensuite · touchez-en un pour la réponse
Copier le lien

Qu'est-ce que try-with-resources et pourquoi le préférer ?

Java essentielmid

Un try qui déclare une ressource entre parenthèses — try (var reader = new FileReader(f)) { ... } — et la ferme automatiquement quand le bloc se termine, succès ou exception.

Un try qui déclare une ressource entre parenthèses — try (var reader = new FileReader(f)) { ... } — et la ferme automatiquement quand le bloc se termine, succès ou exception. La ressource doit juste implémenter AutoCloseable.

Ça remplace le bloc finally propice aux erreurs où les gens oublient de fermer, ou ferment dans le mauvais ordre, ou fuient sur un chemin d'exception. En code de test c'est comme ça que vous gérez proprement fichiers, connexions BD et readers — pas de handles pendants qui épuisent lentement un environnement partagé.

Points clés
  • Déclare une ressource qui se ferme automatiquement à la fin du bloc
  • Marche sur tout AutoCloseable, ferme même sur exception
  • Remplace le nettoyage oubliable du bloc finally
Ils demanderont ensuite · touchez-en un pour la réponse
Copier le lien

Que signifie le mot-clé static, et quand l'utilisez-vous en code de test ?

Java essentielmid

static appartient à la classe, pas à une instance — une copie partagée par tous. Une méthode static est appelée sur la classe (Utils.formatDate()), un champ static est un état partagé, et un bloc…

static appartient à la classe, pas à une instance — une copie partagée par tous. Une méthode static est appelée sur la classe (Utils.formatDate()), un champ static est un état partagé, et un bloc static s'exécute une fois quand la classe se charge.

Dans les frameworks : les méthodes utilitaires qui n'ont pas besoin d'état d'objet sont static ; les constantes sont static final ; un WebDriver partagé dans une classe de base est parfois static (bien que ça pose problème en exécution parallèle). La prudence à exprimer : l'état static mutable est un bug classique de tests parallèles — deux tests partageant un seul driver static s'écrasent mutuellement.

Points clés
  • Appartient à la classe, une seule copie partagée
  • Méthodes static pour les utilitaires sans état ; static final pour les constantes
  • L'état static mutable (un driver partagé) casse les tests parallèles
Ils demanderont ensuite · touchez-en un pour la réponse
Le piège

Recourir à static partout est un smell. L'état static mutable est exactement ce qui rend une suite dangereuse à paralléliser — nommez cette conscience, ne définissez pas juste le mot-clé.

Copier le lien

Qu'est-ce qu'un POJO, et pourquoi compte-t-il en automatisation des tests ?

Java pour l'automatisationmid

Un POJO — Plain Old Java Object — est une classe simple avec des champs, des getters et setters et aucun bagage de framework.

Un POJO — Plain Old Java Object — est une classe simple avec des champs, des getters et setters et aucun bagage de framework. En automatisation c'est comme ça que vous modélisez les données : un POJO User, un POJO Order, un corps de requête ou de réponse.

Il compte le plus en test d'API. Au lieu de fouiller du JSON brut avec des clés en chaînes, vous désérialisez la réponse dans un POJO typé et faites vos assertions sur order.getTotal() — sûr à la compilation, refactorable, lisible. Sérialiser un POJO pour construire un corps de requête bat l'écriture à la main de chaînes JSON qui cassent silencieusement.

Points clés
  • Classe simple : champs + getters/setters, sans liens de framework
  • Modélise les données — User, Order, corps de requête/réponse
  • Test d'API typé : désérialiser le JSON dans un POJO, assertions sur les champs
Ils demanderont ensuite · touchez-en un pour la réponse
Copier le lien

Quelles collections utilisez-vous réellement dans un vrai framework Selenium ?

Java pour l'automatisationsenior

List<WebElement> pour attraper de nombreux éléments — chaque ligne, chaque lien — puis itérer. Map pour les recherches comme des données de test indexées par nom, ou des valeurs attendues par champ.

List<WebElement> pour attraper de nombreux éléments — chaque ligne, chaque lien — puis itérer. Map pour les recherches comme des données de test indexées par nom, ou des valeurs attendues par champ. Set pour affirmer l'unicité — collecter les IDs visibles et prouver qu'il n'y a pas de doublons.

Le détail senior est de savoir pourquoi : findElements renvoie une List ; vous la convertissez en Set quand vous dédupliquez ; vous utilisez une Map pour piloter des vérifications basées sur les données. Il ne s'agit pas de mémoriser l'API, mais de montrer que vous choisissez la structure qui correspond à la question que pose le test.

Points clés
  • List<WebElement> depuis findElements — itérer les lignes/liens
  • Map pour les recherches de données de test et les valeurs attendues
  • Set pour affirmer l'unicité / dédupliquer les valeurs récupérées
Ils demanderont ensuite · touchez-en un pour la réponse
Copier le lien

Utiliseriez-vous les streams Java en code de test ?

Java pour l'automatisationsenior

Oui, là où ils rendent une assertion plus claire. Les streams brillent pour filtrer et transformer des collections que vous avez récupérées : prices.stream().allMatch(p -> p > 0), ou mapper des…

Oui, là où ils rendent une assertion plus claire. Les streams brillent pour filtrer et transformer des collections que vous avez récupérées : prices.stream().allMatch(p -> p > 0), ou mapper des WebElements vers leur texte et collecter dans une List à comparer à l'attendu.

Le jugement, c'est de ne pas en abuser. Un stream court qui se lit comme l'assertion est excellent ; un stream imbriqué de cinq opérations que personne ne peut déboguer est pire qu'une simple boucle. Dans un test, la lisibilité l'emporte — la personne suivante doit voir ce qui est vérifié d'un coup d'œil.

Points clés
  • Excellents pour filter/map/match sur des collections récupérées
  • mapper des WebElements vers du texte, allMatch/anyMatch pour les assertions
  • Gardez-les courts et lisibles — une boucle bat un stream illisible
Ils demanderont ensuite · touchez-en un pour la réponse
Copier le lien

Que fait le mot-clé final ?

Java essentielmid

final veut dire « ne peut pas changer une fois défini ». Une variable final peut être assignée une seule fois (une constante), une méthode final ne peut pas être redéfinie, et une classe final ne…

final veut dire « ne peut pas changer une fois défini ». Une variable final peut être assignée une seule fois (une constante), une méthode final ne peut pas être redéfinie, et une classe final ne peut pas être étendue.

En pratique : final pour les constantes (URLs de base, timeouts en static final), et pour verrouiller un champ qu'une classe ne devrait pas réassigner. Ça signale l'intention — « ceci ne change pas » — sur laquelle le compilateur et le lecteur suivant s'appuient tous deux. En abuser sur chaque variable locale est du bruit, mais sur les constantes et les champs clés ça documente des garanties.

Points clés
  • variable final = assigner une fois ; méthode = pas de redéfinition ; classe = pas d'extension
  • À utiliser pour les constantes (static final) et les champs verrouillés
  • Signale « ceci ne change pas » au compilateur et au lecteur
Ils demanderont ensuite · touchez-en un pour la réponse
Copier le lien
Ils demanderont ensuite