package de.superx.dbt.model; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.File; import java.nio.file.Path; import java.util.List; import java.util.StringJoiner; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.support.rowset.SqlRowSet; import de.superx.BIATestUtils; import de.superx.BaseDbTest; import de.superx.bianalysis.ReportDefinition; import de.superx.bianalysis.models.Right; import de.superx.bianalysis.rest.BiAnalysisApi; import de.superx.dbt.DbtAction; import de.superx.dbt.DbtRunRequest; import de.superx.dbt.DbtRunResult; import de.superx.dbt.DbtWrapper; import de.superx.dbt.DbtExecutionState; import de.superx.rest.EtlJobApi; import de.superx.rest.model.Result; import de.superx.rest.model.Row; import de.superx.util.PathAndFileUtils; public class DbtRunAndMeasureTest extends BaseDbTest { static Logger logger = LoggerFactory.getLogger(DbtRunAndMeasureTest.class); @Autowired BiAnalysisApi biAnalysis; @Autowired EtlJobApi api; @Autowired DbtWrapper dbtWrapper; private JdbcTemplate jt; @Before public void setUp() { jt = new JdbcTemplate(dataSource); setRight(Right.CREATE_ANALYSIS); } public static final String BI_ANALYSIS_FIXTURES = String.join(File.separator, "test", "resources", "db", "fixtures" ); /* * Idee: Wir holen uns Kennzahlen/Auswertungen mit Hilfe der "BI-Analysen". * Dann ändern wir etwas im Vorsystem (oder hier, für die Testfälle, erstmal nur * im staging-area, welches die Vorsystemdaten 1:1 abbilden sollte!?), lassen * die dbt-Transformation laufen, und prüfen ein weiteres Mal die Auswertung. * Die Änderungen im Vorsystem sollten ihre Entsprechung in der Auswertung haben. * 1. Testfall: Wir prüfen die Propagierung der Änderung des Geschlechts eines * Bewerbers. */ @Test public void testTransferOfChanges() throws InterruptedException { String requestFile = BI_ANALYSIS_FIXTURES + File.separator + "applicants_by_gender_request.json"; ReportDefinition definition = BIATestUtils.getReportDefinitionFromFile(requestFile); // Ausgangslage feststellen und merken Result result_before = null; try { result_before = biAnalysis.getReport(definition); } catch (Exception e) { throw new RuntimeException(e); } // ids der Genderschlüssel "männlich"/"weiblich" ermitteln String gender_sql = "SELECT id, defaulttext FROM staging.k_gender WHERE defaulttext IN ('männlich', 'weiblich');"; SqlRowSet gender_rows = jt.queryForRowSet(gender_sql); gender_rows.beforeFirst(); int male_key_id = -1; int female_key_id = -1; while(gender_rows.next()) { if (gender_rows.getString("defaulttext").equals("männlich")) { male_key_id = gender_rows.getInt("id"); } else if (gender_rows.getString("defaulttext").equals("weiblich")) { female_key_id = gender_rows.getInt("id"); } } // einen männlichen Bewerber raussuchen und seine Personen-Id merken String person_id_sql = "SELECT id FROM staging.person WHERE id IN " + "(SELECT person_id FROM staging.applicant) AND k_gender_id = " + male_key_id + " LIMIT 1;"; SqlRowSet applicants = jt.queryForRowSet(person_id_sql); applicants.beforeFirst(); int applicant_person_id = -1; while(applicants.next()) { applicant_person_id = applicants.getInt("id"); } // Geschlecht des Bewerbers auf "weiblich" ändern String alter_applicant_sql = "UPDATE staging.person SET k_gender_id = " + female_key_id + " WHERE id = " + applicant_person_id; jt.execute(alter_applicant_sql); // Bewerber nach dim_person_applicant inkrementell laden DbtRunRequest request = new DbtRunRequest(DbtAction.BUILD, "hisinone", "+dim_person_applicant"); DbtRunResult result = dbtWrapper.execute(request); if (result.getState() != DbtExecutionState.SUCCESS) { List errors = result.getErrorMessages(); StringJoiner joiner = new StringJoiner("\n"); for (String error : errors) { joiner.add(error); } Assert.fail(joiner.toString()); } // Lage nach Änderung und dbt-Transformation feststellen Result result_after = null; try { result_after = biAnalysis.getReport(definition); } catch (Exception e) { throw new RuntimeException(e); } // Werte vergleichen: Wegen Änderung sollte ein Bewerber weniger, eine Bewerbering mehr sein Long male_before = lookupValue(result_before,"app_basic:3", "männlich","Kennzahl|app_basic:80"); Long female_before = lookupValue(result_before,"app_basic:3", "weiblich","Kennzahl|app_basic:80"); Long male_after = lookupValue(result_after,"app_basic:3", "männlich", "Kennzahl|app_basic:80"); Long female_after = lookupValue(result_after,"app_basic:3", "weiblich","Kennzahl|app_basic:80"); assertEquals("Anzahl der männlichen Bewerber sollte um 1 abgenommen haben", male_before.intValue(), male_after.intValue() + 1); assertEquals("Anzahl der weiblichen Bewerber sollte um 1 zugenommen haben", female_before.intValue(), female_after.intValue() - 1); // Geschlecht des Bewerbers wieder auf "männlich" ändern // Soll danach noch dbt laufen? (erstmal weg lassen) String reset_applicant_sql = "UPDATE staging.person SET k_gender_id = " + male_key_id + " WHERE id = " + applicant_person_id; jt.execute(reset_applicant_sql); } /* * Wir prüfen das Entfernen der Bewerbernummer nach "Löschung" eines Bewerbers. */ @Test public void testRemoveApplicantNumber() throws InterruptedException { String requestFile = BI_ANALYSIS_FIXTURES + File.separator + "applicants_by_applicantnumber.json"; ReportDefinition definition = BIATestUtils.getReportDefinitionFromFile(requestFile); // Ausgangslage feststellen und merken Result result_before = null; try { result_before = biAnalysis.getReport(definition); } catch (Exception e) { throw new RuntimeException(e); } // einen Bewerber raussuchen und seine Bewerber-Id merken String person_id_sql = "SELECT DISTINCT p.id, a.id AS applicant_id, a.applicantnumber " + "FROM staging.applicant AS a " + "JOIN staging.person AS p ON a.person_id = p.id " + "LEFT JOIN presentation.fact_application AS fa ON fa.applicant_id = a.id " + "WHERE fa.applicant_id IS NOT NULL ORDER BY id LIMIT 1"; SqlRowSet person_applicants = jt.queryForRowSet(person_id_sql); person_applicants.beforeFirst(); int person_id = -1; int applicantnumber = -1; int applicant_id = -1; while(person_applicants.next()) { person_id = person_applicants.getInt("id"); applicantnumber = person_applicants.getInt("applicantnumber"); applicant_id = person_applicants.getInt("applicant_id"); } int dummy_id = -10; // Löschen eines Bewerbers durch Änderung der Bewerberid simulieren String alter_person_sql = "UPDATE staging.applicant SET (id, person_id) = (" + dummy_id + ", " + dummy_id + ")" + " WHERE id = " + applicant_id + ";"; jt.execute(alter_person_sql); // Bewerber nach dim_person_applicant inkrementell laden DbtRunRequest request = new DbtRunRequest(DbtAction.BUILD, "hisinone", "+dim_person_applicant"); DbtRunResult result = dbtWrapper.execute(request); if (result.getState() != DbtExecutionState.SUCCESS) { List errors = result.getErrorMessages(); StringJoiner joiner = new StringJoiner("\n"); for (String error : errors) { joiner.add(error); } Assert.fail(joiner.toString()); } // Lage nach Änderung und dbt-Transformation feststellen Result result_after = null; try { result_after = biAnalysis.getReport(definition); } catch (Exception e) { throw new RuntimeException(e); } // Werte vergleichen: Wegen Änderung sollte ein Bewerber keine Bewerbernummer mehr haben Long no_number_before = lookupValue(result_before, "app_basic:162","n. v.","Kennzahl|app_basic:80"); Long no_number_after = lookupValue(result_after, "app_basic:162","n. v.","Kennzahl|app_basic:80"); if(no_number_before == null) { no_number_before = Long.valueOf(0); } if(no_number_after == null) { no_number_after = Long.valueOf(0); } // Zurücksetzen der Änderungen, durch das ändern der id hat sich auch die snapshot-Tabelle aktualisiert // Soll danach noch dbt laufen? (erstmal weg lassen) String reset_applicant_sql = "UPDATE staging.applicant SET (id, person_id) = (" + applicant_id + ", "+ dummy_id + " )" + " WHERE id = " + dummy_id + ";"; String reset_applicant_sql2 = "UPDATE presentation.dim_person_applicant SET applicantnumber = " + applicantnumber + " WHERE src_person_id = " + person_id + ";"; String reset_applicant_snapshot_sql = "UPDATE snapshots.person_academicdegree_snapshot SET dbt_valid_to = NULL" + " WHERE id = " + person_id + ";"; String delete_dummy_applicant_sql = "DELETE FROM snapshots.person_academicdegree_snapshot WHERE id = " + dummy_id + ";"; //jt.execute(reset_applicant_sql + reset_applicant_sql2 + reset_applicant_snapshot_sql + delete_dummy_applicant_sql); assertEquals("Anzahl der Bewerber ohne Bewerbernummer sollte um 1 zugenommen haben", no_number_before.intValue() + 1, no_number_after.intValue()); } /* * Wir prüfen das die Bewerbernamen nie in Auswertungen ausgegeben werden. */ @Test public void testNeverNameForApplicants() throws InterruptedException { String requestFile = BI_ANALYSIS_FIXTURES + File.separator + "applicants_by_name.json"; ReportDefinition definition = BIATestUtils.getReportDefinitionFromFile(requestFile); // Result erstellen Result result = null; try { result = biAnalysis.getReport(definition); } catch (Exception e) { throw new RuntimeException(e); } // Anzahl der Bewerber herausfinden (Es gibt auch Bewerber ohne Bewerbung, die werden nicht betrachtet) String count_applicants_sql = "SELECT COUNT(DISTINCT person_id) FROM presentation.fact_application;"; SqlRowSet count_applicants = jt.queryForRowSet(count_applicants_sql); count_applicants.beforeFirst(); int applicant_count = 0; while(count_applicants.next()) { applicant_count = count_applicants.getInt("count"); } // Bewerber sollen nie Namen haben Long numberOfApplicantsWithoutNames = lookupValue(result, "app_basic:12391","n. v.","Kennzahl|app_basic:80"); if(numberOfApplicantsWithoutNames == null) { numberOfApplicantsWithoutNames = Long.valueOf(0); } assertEquals("Anzahl der Bewerber mit n. v. als Namen sollte der gleichen Anzahl an Bewerbern entsprechen", applicant_count, numberOfApplicantsWithoutNames.intValue()); } private static Long lookupValue(Result result, String key, String value, String measure_key) { for (Row row : result.rows) { String rvalue = (String)row.cells.get(key); if (value.equals(rvalue)) { return (Long)row.cells.get(measure_key); } } return null; } }