Il semble que vous comprendre la structure de base/syntaxe de la façon d'écrire des tests unitaires et de tests de CodeIgniter code ne doit pas être différent de test de non-code de CI, je tiens donc à vous concentrer sur vos préoccupations sous-jacentes/questions ...
J'ai eu les mêmes questions il y a pas longtemps avec PHPUnit. Comme quelqu'un sans formation formelle, j'ai trouvé que le Test Unitaire état d'esprit semble abstrait et artificiel au premier abord. Je pense que la principale raison pour cela-dans mon cas, et probablement le vôtre aussi, à partir de la question -- c'est que vous n'avez pas porté sur VRAIMENT de travail pour séparer les préoccupations dans votre code jusqu'à maintenant.
Le test affirmations semblent abstraites parce que la plupart de vos méthodes/fonctions susceptibles d'effectuer plusieurs tâches distinctes. La réussite du test mentalité nécessite un changement dans la façon dont vous pensez à votre code. Vous devriez arrêter de définir le succès en termes de "ça marche?" Au lieu de cela, vous devriez vous demander: "est-ce de travailler, il va bien jouer avec un autre code, il est conçu d'une manière qui le rend utile dans d'autres applications, et puis-je vérifier qu'il fonctionne?"
Par exemple, ci-dessous est un exemple simplifié de la façon dont vous avez écrit le code jusqu'à ce point:
function parse_remote_page_txt($type = 'index')
{
$remote_file = ConfigSingleton::$config_remote_site . "$type.php";
$local_file = ConfigSingleton::$config_save_path;
if ($txt = file_get_contents($remote_file)) {
if ($values_i_want_to_save = preg_match('//', $text)) {
if (file_exists($local_file)) {
$fh = fopen($local_file, 'w+');
fwrite($fh, $values_i_want_to_save);
fclose($fh);
return TRUE;
} else {
return FALSE;
}
} else {
return FALSE;
}
}
Exactement ce qui se passe ici n'est pas important. Je vais essayer d'expliquer pourquoi ce code est difficile à tester:
C'est à l'aide d'un singleton classe de configuration pour générer des valeurs. La réussite de votre fonction dépend des valeurs de singleton, et comment pouvez-vous vérifier que cette fonction fonctionne correctement dans un isolement complet lorsque vous ne peut pas instancier la nouvelle configuration des objets avec des valeurs différentes? Une meilleure option pourrait être de passer votre fonction d'un $config
argument qui consiste en une config objet ou un tableau dont les valeurs que vous pouvez contrôler. C'est largement appelé "l'Injection de Dépendance" et il y a des discussions de cette technique sur les interwebs.
Avis imbriquée IF
des déclarations. Des moyens d'essai vous êtes couvrant tous les fichiers exécutables ligne avec une sorte de test. Lorsque vous imbriquez des instructions if vous êtes à la création de nouvelles branches de code qui nécessitent un nouveau test de chemin.
Enfin, vous voyez comment cette fonction, bien qu'il semble être de faire une chose (de l'analyse du contenu d'un fichier distant) est en fait l'exécution de plusieurs tâches? Si vous avec zèle séparer de vos préoccupations à votre code devient infiniment plus testable. Beaucoup plus testable façon de faire la même chose, ce serait ...
class RemoteParser() {
protected $local_path;
protected $remote_path;
protected $config;
/**
* Class constructor -- forces injection of $config object
* @param ConfigObj $config
*/
public function __construct(ConfigObj $config) {
$this->config = $config;
}
/**
* Setter for local_path property
* @param string $filename
*/
public function set_local_path($filename) {
$file = filter_var($filename);
$this->local_path = $this->config->local_path . "/$file.html";
}
/**
* Setter for remote_path property
* @param string $filename
*/
public function set_remote_path($filename) {
$file = filter_var($filename);
$this->remote_path = $this->config->remote_site . "/$file.html";
}
/**
* Retrieve the remote source
* @return string Remote source text
*/
public function get_remote_path_src() {
if ( ! $this->remote_path) {
throw new Exception("you didn't set the remote file yet!");
}
if ( ! $this->local_path) {
throw new Exception("you didn't set the local file yet!");
}
if ( ! $remote_src = file_get_contents($this->remote_path)) {
throw new Exception("we had a problem getting the remote file!");
}
return $remote_src;
}
/**
* Parse a source string for the values we want
* @param string $src
* @return mixed Values array on success or bool(FALSE) on failure
*/
public function parse_remote_src($src='') {
$src = filter_validate($src);
if (stristr($src, 'value_we_want_to_find')) {
return array('val1', 'val2');
} else {
return FALSE;
}
}
/**
* Getter for remote file path property
* @return string Remote path
*/
public function get_remote_path() {
return $this->remote_path;
}
/**
* Getter for local file path property
* @return string Local path
*/
public function get_local_path() {
return $this->local_path;
}
}
Comme vous pouvez le voir, chacune de ces méthodes de la classe gère une fonction particulière de la classe qui est facilement vérifiable. A la récupération de fichiers à distance de travail? A nous de trouver les valeurs qui nous ont été d'essayer de l'analyser? Etc. Tout d'un coup ceux résumé des affirmations semblent beaucoup plus utile.
À mon humble avis, le plus de vous plonger dans les tests le plus vous vous rendez compte qu'il est plus sur le code de bonne conception et sensible de l'architecture que de simplement s'assurer que les choses fonctionnent comme prévu. Et c'est là où les avantages de la programmation orientée objet vraiment commencer à briller. Vous pouvez tester le code de procédure de l'amende juste, mais pour un grand projet avec les parties interdépendantes test a un moyen de l'application d'une bonne conception. Je sais que ça peut être un troll appât pour certains de procédure gens, mais bon.
Plus vous test, plus vous allez trouver vous-même à l'écriture de code et de vous demander, "Vais-je être en mesure de tester cela?" Et si non, vous aurez probablement changer la structure.
Toutefois, le code n'a pas besoin d'être élémentaire pour être testées. Stubbing et se moquant vous permet de tester les opérations extérieures de la réussite ou de l'échec de ce qui est totalement hors de contrôle. Vous pouvez créer des montages de test opérations de base de données et n'importe quoi d'autre.
Plus je test, plus je me rends compte que si je vais avoir un moment difficile de tests de quelque chose, il est plus probable parce que j'ai une conception sous-jacente du problème. Si je redresser qu'il résulte généralement dans toutes les barres vertes dans mes résultats de test.
Enfin, voici quelques liens qui m'ont vraiment aidé à commencer à penser dans un test-d'une façon amicale. La première est une langue-dans-joue liste de choses à ne PAS faire si vous voulez écrire de code de tests. En fait, si vous parcourir l'ensemble de ce site vous trouverez beaucoup de trucs utiles qui aideront à vous mettre sur le chemin d'accès à 100% de couverture de code. Un autre article utile est cette discussion de l'injection de dépendance.
Bonne chance!