a macro %ut_assert_dataset_content est un pilier pour la mise en place de tests unitaires (CI/CD) dans un environnement SAS, permettant de garantir la non-régression lors de modifications de code. Sa force réside dans l'exploitation intelligente de la variable macro automatique &SYSINFO, générée par la PROC COMPARE. Contrairement à une vérification visuelle, cette approche programmatique permet d'automatiser la validation de milliers d'observations en une fraction de seconde.
L'expertise technique ici se concentre sur l'utilisation du masque binaire (bmask) et de la fonction logique %SYSFUNC(BAND). Par défaut, PROC COMPARE peut signaler des différences mineures (comme un format ou un libellé différent) qui ne sont pas toujours critiques. En appliquant un masque de bits (opérateur AND), vous filtrez les codes de retour pour ne faire échouer le test que sur des critères fondamentaux : valeurs de données discordantes, observations manquantes ou structures de variables divergentes.
Une astuce d'expert pour renforcer ce test consiste à toujours s'assurer que vos datasets sont triés selon la même clé avant l'appel de la macro, car une différence dans l'ordre des observations activerait le bit de comparaison de &SYSINFO même si les données brutes sont identiques. L'intégration de cette assertion dans un framework de log (%ut_log_result) permet enfin de générer des rapports de conformité prêts pour l'audit.
Type : EXTERNE
La macro ne crée ni ne lit de données par elle-même. Elle opère sur deux datasets (`ds_01` et `ds_02`) qui doivent être fournis en tant que paramètres par l'environnement d'appel. L'origine de ces données est donc externe à la macro.
| 1 | %macro ut_assert_dataset_content(description=, ds_01=, ds_02=, bmask=1111111100000000, expected_result=PASS); |
| 2 | /* |
| 3 | To be used to assert dataset contents are equals |
| 4 | description: description to explain why ds_01 content should be equal to ds_02 content |
| 5 | ds_01: name of the first dataset |
| 6 | ds_02: name of the second dataset |
| 7 | */ |
| 8 | *-- Exit IF framework state is erroneous --*; |
| 9 | %IF &ut_state. %THEN %DO; |
| 10 | %return; |
| 11 | %END; |
| 12 | |
| 13 | %ut_tst_init(type=ut_assert_dataset_content, description=&description., expected_result=&expected_result.); |
| 14 | |
| 15 | PROC COMPARE DATA=&ds_01. compare=&ds_02. noprint; |
| 16 | RUN; |
| 1 | *-- Convert the binary mask to numeric --*; |
| 2 | %local nmask; |
| 3 | %let nmask = %sysfunc(inputn(&bmask., binary16.)); |
| 4 | |
| 5 | *-- Use sysinfo and bmask to identify if any relevant bit is active --*; |
| 6 | %local rec; |
| 7 | %let res = %sysfunc(band(&sysinfo., &nmask.)); |
| 8 | |
| 9 | %IF &res. = 0 %THEN %DO; |
| 10 | %let ut_tst_res = PASS; |
| 11 | %let ut_tst_det = Datasets &ds_01. and &ds_02. have the same content; |
| 12 | %END; |
| 13 | %ELSE %DO; |
| 14 | %let ut_tst_res = FAIL; |
| 15 | %let ut_tst_det = Datasets &ds_01. and &ds_02. have different content; |
| 16 | %END; |
| 17 | |
| 18 | %ut_log_result; |
| 19 | %mend ut_assert_dataset_content; |