diff --git a/pom.xml b/pom.xml index a3e3390..0708a82 100644 --- a/pom.xml +++ b/pom.xml @@ -145,5 +145,5 @@ pentaho-kettle-dataset - 3.2.0-SNAPSHOT + 3.3.0-SNAPSHOT diff --git a/src/main/java/org/pentaho/di/dataset/TransUnitTest.java b/src/main/java/org/pentaho/di/dataset/TransUnitTest.java index f5ec719..78ec21c 100644 --- a/src/main/java/org/pentaho/di/dataset/TransUnitTest.java +++ b/src/main/java/org/pentaho/di/dataset/TransUnitTest.java @@ -22,28 +22,24 @@ package org.pentaho.di.dataset; -import java.io.File; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - import org.apache.commons.lang.StringUtils; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.logging.LogChannelInterface; -import org.pentaho.di.core.row.RowMeta; -import org.pentaho.di.core.row.RowMetaInterface; import org.pentaho.di.core.variables.VariableSpace; -import org.pentaho.di.dataset.spoon.xtpoint.RowCollection; import org.pentaho.di.dataset.util.DataSetConst; import org.pentaho.di.dataset.util.FactoriesHierarchy; import org.pentaho.metastore.persist.MetaStoreAttribute; import org.pentaho.metastore.persist.MetaStoreElementType; +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + /** * This class describes a test-case where a transformation output is verified against golden data. - * - * @author matt * + * @author matt */ @MetaStoreElementType( name = "Kettle Transformation Unit Test", @@ -63,7 +59,7 @@ public class TransUnitTest { @MetaStoreAttribute( key = "transformation_filename" ) protected String transFilename; // file (3rd priority) - + @MetaStoreAttribute( key = "input_data_sets" ) protected List inputDataSets; @@ -73,10 +69,10 @@ public class TransUnitTest { @MetaStoreAttribute( key = "trans_test_tweaks" ) protected List tweaks; - @MetaStoreAttribute( key = "test_type") + @MetaStoreAttribute( key = "test_type" ) protected TestType type; - - @MetaStoreAttribute( key = "persist_filename") + + @MetaStoreAttribute( key = "persist_filename" ) protected String filename; @MetaStoreAttribute @@ -88,6 +84,10 @@ public class TransUnitTest { @MetaStoreAttribute protected List variableValues; + @MetaStoreAttribute + protected boolean autoOpening; + + public TransUnitTest() { inputDataSets = new ArrayList(); goldenDataSets = new ArrayList(); @@ -96,16 +96,18 @@ public TransUnitTest() { databaseReplacements = new ArrayList(); variableValues = new ArrayList<>(); basePath = null; - } - - public TransUnitTest( String name, String description, - String transObjectId, String transRepositoryPath, String transFilename, - List inputDataSets, - List goldenDataSets, - List tweaks, - TestType type, - String filename, - List databaseReplacements) { + autoOpening = false; + } + + public TransUnitTest( String name, String description, + String transObjectId, String transRepositoryPath, String transFilename, + List inputDataSets, + List goldenDataSets, + List tweaks, + TestType type, + String filename, + List databaseReplacements, + boolean autoOpening ) { this(); this.name = name; this.description = description; @@ -118,37 +120,38 @@ public TransUnitTest( String name, String description, this.type = type; this.filename = filename; this.databaseReplacements = databaseReplacements; + this.autoOpening = autoOpening; } - + @Override public boolean equals( Object obj ) { - if (obj==this) { + if ( obj == this ) { return true; } - if (!(obj instanceof TransUnitTest)) { + if ( !( obj instanceof TransUnitTest ) ) { return false; } - return ((TransUnitTest)obj).name.equalsIgnoreCase( name ); + return ( (TransUnitTest) obj ).name.equalsIgnoreCase( name ); } - + @Override public int hashCode() { return name.hashCode(); } - public TransUnitTestSetLocation findGoldenLocation(String stepName) { - for (TransUnitTestSetLocation location : goldenDataSets) { - if (stepName.equalsIgnoreCase( location.getStepname() )) { + public TransUnitTestSetLocation findGoldenLocation( String stepName ) { + for ( TransUnitTestSetLocation location : goldenDataSets ) { + if ( stepName.equalsIgnoreCase( location.getStepname() ) ) { return location; } } return null; } - public TransUnitTestSetLocation findInputLocation(String stepName) { - for (TransUnitTestSetLocation location : inputDataSets) { - if (stepName.equalsIgnoreCase( location.getStepname() )) { + public TransUnitTestSetLocation findInputLocation( String stepName ) { + for ( TransUnitTestSetLocation location : inputDataSets ) { + if ( stepName.equalsIgnoreCase( location.getStepname() ) ) { return location; } } @@ -158,14 +161,13 @@ public TransUnitTestSetLocation findInputLocation(String stepName) { /** * Retrieve the golden data set for the specified location * - * @param log the logging channel to log to + * @param log the logging channel to log to * @param hierarchy The factories to load sets with - * @param location the location where we want to check against golden rows + * @param location the location where we want to check against golden rows * @return The golden data set - * * @throws KettleException */ - public DataSet getGoldenDataSet(LogChannelInterface log, FactoriesHierarchy hierarchy, TransUnitTestSetLocation location) throws KettleException { + public DataSet getGoldenDataSet( LogChannelInterface log, FactoriesHierarchy hierarchy, TransUnitTestSetLocation location ) throws KettleException { String stepName = location.getStepname(); String goldenDataSetName = location.getDataSetName(); @@ -173,29 +175,31 @@ public DataSet getGoldenDataSet(LogChannelInterface log, FactoriesHierarchy hier try { // Look in the golden data sets list for the mentioned step name // - if (goldenDataSetName==null) { - throw new KettleException("Unable to find golden data set for step '"+stepName+"'"); + if ( goldenDataSetName == null ) { + throw new KettleException( "Unable to find golden data set for step '" + stepName + "'" ); } DataSet goldenDataSet = hierarchy.getSetFactory().loadElement( goldenDataSetName ); - if (goldenDataSet==null) { - throw new KettleException("Unable to find golden data set '"+goldenDataSetName+"' for step '"+stepName+"'"); + if ( goldenDataSet == null ) { + throw new KettleException( "Unable to find golden data set '" + goldenDataSetName + "' for step '" + stepName + "'" ); } return goldenDataSet; } catch ( Exception e ) { - throw new KettleException( "Unable to retrieve sorted golden row data set '"+stepName+"'", e ); + throw new KettleException( "Unable to retrieve sorted golden row data set '" + stepName + "'", e ); } } - /** Find the first tweak for a certain step + /** + * Find the first tweak for a certain step + * * @param stepname the name of the step on which a tweak is put * @return the first tweak for a certain step or null if nothing was found */ - public TransUnitTestTweak findTweak(String stepname) { - for (TransUnitTestTweak tweak : tweaks) { - if (tweak.getStepName()!=null && tweak.getStepName().equalsIgnoreCase(stepname)) { + public TransUnitTestTweak findTweak( String stepname ) { + for ( TransUnitTestTweak tweak : tweaks ) { + if ( tweak.getStepName() != null && tweak.getStepName().equalsIgnoreCase( stepname ) ) { return tweak; } } @@ -204,42 +208,43 @@ public TransUnitTestTweak findTweak(String stepname) { /** * Remove all input and golden data sets on the step with the provided name + * * @param stepname the name of the step for which we need to clear out all input and golden data sets */ - public void removeInputAndGoldenDataSets(String stepname) { + public void removeInputAndGoldenDataSets( String stepname ) { - for (Iterator iterator = inputDataSets.iterator() ; iterator.hasNext() ; ) { + for ( Iterator iterator = inputDataSets.iterator(); iterator.hasNext(); ) { TransUnitTestSetLocation inputLocation = iterator.next(); - if (inputLocation.getStepname().equalsIgnoreCase(stepname)) { + if ( inputLocation.getStepname().equalsIgnoreCase( stepname ) ) { iterator.remove(); } } - for (Iterator iterator = goldenDataSets.iterator() ; iterator.hasNext() ; ) { + for ( Iterator iterator = goldenDataSets.iterator(); iterator.hasNext(); ) { TransUnitTestSetLocation goldenLocation = iterator.next(); - if (goldenLocation.getStepname().equalsIgnoreCase(stepname)) { + if ( goldenLocation.getStepname().equalsIgnoreCase( stepname ) ) { iterator.remove(); } } } - public String calculateCompleteFilename( VariableSpace space) { + public String calculateCompleteFilename( VariableSpace space ) { String baseFilePath = space.environmentSubstitute( basePath ); - if ( StringUtils.isEmpty(baseFilePath) ) { + if ( StringUtils.isEmpty( baseFilePath ) ) { // See if the base path environment variable is set // baseFilePath = space.getVariable( DataSetConst.VARIABLE_UNIT_TESTS_BASE_PATH ); } - if (StringUtils.isEmpty( baseFilePath )) { - baseFilePath=""; + if ( StringUtils.isEmpty( baseFilePath ) ) { + baseFilePath = ""; } - if (StringUtils.isNotEmpty( baseFilePath )) { - if (!baseFilePath.endsWith( File.separator )) { - baseFilePath+=File.separator; + if ( StringUtils.isNotEmpty( baseFilePath ) ) { + if ( !baseFilePath.endsWith( File.separator ) ) { + baseFilePath += File.separator; } } - return baseFilePath+transFilename; + return baseFilePath + transFilename; } /** @@ -449,4 +454,20 @@ public List getVariableValues() { public void setVariableValues( List variableValues ) { this.variableValues = variableValues; } + + /** + * Gets autoOpening + * + * @return value of autoOpening + */ + public boolean isAutoOpening() { + return autoOpening; + } + + /** + * @param autoOpening The autoOpening to set + */ + public void setAutoOpening( boolean autoOpening ) { + this.autoOpening = autoOpening; + } } diff --git a/src/main/java/org/pentaho/di/dataset/spoon/DataSetHelper.java b/src/main/java/org/pentaho/di/dataset/spoon/DataSetHelper.java index 467c749..6ce2240 100755 --- a/src/main/java/org/pentaho/di/dataset/spoon/DataSetHelper.java +++ b/src/main/java/org/pentaho/di/dataset/spoon/DataSetHelper.java @@ -118,7 +118,7 @@ public void updateMenu( Document doc ) { public void manage() { } - public List getAvailableDatabases( Repository repository ) throws KettleException { + public static List getAvailableDatabases( Repository repository ) throws KettleException { List list = new ArrayList(); // Load database connections from the central repository if we're connected to one @@ -725,7 +725,7 @@ public void clearGoldenDataSet() { transGraph.redraw(); } - private FactoriesHierarchy getHierarchy() throws KettleException { + public static FactoriesHierarchy getHierarchy() throws KettleException { try { Spoon spoon = Spoon.getInstance(); @@ -1239,6 +1239,61 @@ public void switchUnitTest( TransUnitTest targetTest, TransMeta transMeta ) { Spoon.getInstance().refreshGraph(); } + public static List findTransformationUnitTest( TransMeta transMeta, IMetaStore metaStore ) { + MetaStoreFactory factory = new MetaStoreFactory( TransUnitTest.class, metaStore, PentahoDefaults.NAMESPACE ); + List tests = new ArrayList(); + + try { + + List allTests = factory.getElements(); + for ( TransUnitTest test : allTests ) { + // Match the filename + // + if ( StringUtils.isNotEmpty( transMeta.getFilename() ) ) { + + // What's the transformation absolute URI + // + FileObject transFile = KettleVFS.getFileObject( transMeta.getFilename() ); + String transUri = transFile.getName().getURI(); + + // What's the filename referenced in the test? + // + FileObject testTransFile = KettleVFS.getFileObject( test.calculateCompleteFilename(transMeta) ); + if (testTransFile.exists()) { + String testTransUri = testTransFile.getName().getURI(); + + if ( transUri.equals( testTransUri ) ) { + tests.add( test ); + } + } + } else { + if ( transMeta.getRepository() != null ) { + // No filename, check the object_id ... + // + if ( transMeta.getObjectId() != null && transMeta.getObjectId().getId().equals( test.getTransObjectId() ) ) { + tests.add( test ); + } else { + // Try the repository path.. + // + // What is the repsository path? + String repositoryPath = transMeta.getRepositoryDirectory().getPath() + "/" + transMeta.getName(); + if ( repositoryPath.equals( test.getTransRepositoryPath() ) ) { + tests.add( test ); + } + } + } + } + } + + } catch ( Exception exception ) { + new ErrorDialog( Spoon.getInstance().getShell(), + BaseMessages.getString( PKG, "ShowUnitTestMenuExtensionPoint.ErrorFindingUnitTestsForTransformation.Title" ), + BaseMessages.getString( PKG, "ShowUnitTestMenuExtensionPoint.ErrorFindingUnitTestsForTransformation.Message" ), + exception ); + } + return tests; + } + /** * Gets activeTests * diff --git a/src/main/java/org/pentaho/di/dataset/spoon/dialog/TransUnitTestDialog.java b/src/main/java/org/pentaho/di/dataset/spoon/dialog/TransUnitTestDialog.java index 704b5e3..5178098 100644 --- a/src/main/java/org/pentaho/di/dataset/spoon/dialog/TransUnitTestDialog.java +++ b/src/main/java/org/pentaho/di/dataset/spoon/dialog/TransUnitTestDialog.java @@ -77,6 +77,7 @@ public class TransUnitTestDialog extends Dialog { private Combo wTestType; private TextVar wFilename; private TextVar wBasePath; + private Button wAutoOpen; private TableView wDbReplacements; private TableView wVariableValues; @@ -217,6 +218,25 @@ public boolean open() { wBasePath.setLayoutData( fdBasePath ); lastControl = wBasePath; + // The base path for relative test path resolution + // + Label wlAutoOpen = new Label( shell, SWT.RIGHT ); + props.setLook( wlAutoOpen ); + wlAutoOpen.setText( BaseMessages.getString( PKG, "TransUnitTestDialog.AutoOpen.Label" ) ); + FormData fdlAutoOpen = new FormData(); + fdlAutoOpen.top = new FormAttachment( lastControl, margin ); + fdlAutoOpen.left = new FormAttachment( 0, 0 ); + fdlAutoOpen.right = new FormAttachment( middle, -margin ); + wlAutoOpen.setLayoutData( fdlAutoOpen ); + wAutoOpen = new Button( shell, SWT.CHECK ); + props.setLook( wAutoOpen ); + FormData fdAutoOpen = new FormData(); + fdAutoOpen.top = new FormAttachment( lastControl, margin ); + fdAutoOpen.left = new FormAttachment( middle, 0 ); + fdAutoOpen.right = new FormAttachment( 100, 0 ); + wAutoOpen.setLayoutData( fdAutoOpen ); + lastControl = wAutoOpen; + // The list of database replacements in the unit test transformation // Label wlFieldMapping = new Label( shell, SWT.NONE ); @@ -346,6 +366,7 @@ public void getData() { wTestType.setText( Const.NVL( DataSetConst.getTestTypeDescription( transUnitTest.getType() ), "" ) ); wFilename.setText( Const.NVL( transUnitTest.getFilename(), "" ) ); wBasePath.setText( Const.NVL( transUnitTest.getBasePath(), "" ) ); + wAutoOpen.setSelection( transUnitTest.isAutoOpening() ); for ( int i = 0; i < transUnitTest.getDatabaseReplacements().size(); i++ ) { TransUnitTestDatabaseReplacement dbReplacement = transUnitTest.getDatabaseReplacements().get( i ); @@ -380,6 +401,7 @@ public void getInfo( TransUnitTest test ) { test.setType( DataSetConst.getTestTypeForDescription( wTestType.getText() ) ); test.setFilename( wFilename.getText() ); test.setBasePath( wBasePath.getText() ); + test.setAutoOpening( wAutoOpen.getSelection() ); test.getDatabaseReplacements().clear(); int nrFields = wDbReplacements.nrNonEmpty(); diff --git a/src/main/java/org/pentaho/di/dataset/spoon/dialog/messages/messages_en_US.properties b/src/main/java/org/pentaho/di/dataset/spoon/dialog/messages/messages_en_US.properties index 78ad11b..078d6b2 100644 --- a/src/main/java/org/pentaho/di/dataset/spoon/dialog/messages/messages_en_US.properties +++ b/src/main/java/org/pentaho/di/dataset/spoon/dialog/messages/messages_en_US.properties @@ -61,7 +61,7 @@ TransUnitTestDialog.Filename.Label = Test Transformation filename (Optional) TransUnitTestDialog.RelativePath.Label = Store relative path? TransUnitTestDialog.BasePath.Label = Base test path - +TransUnitTestDialog.AutoOpen.Label = Open automatically in Spoon? TransUnitTestDialog.VariableValues.Label = Variables TransUnitTestDialog.VariableValues.ColumnInfo.VariableName = Name diff --git a/src/main/java/org/pentaho/di/dataset/spoon/xtpoint/AutoOpenTestExtensionPoint.java b/src/main/java/org/pentaho/di/dataset/spoon/xtpoint/AutoOpenTestExtensionPoint.java new file mode 100644 index 0000000..6fb8ab6 --- /dev/null +++ b/src/main/java/org/pentaho/di/dataset/spoon/xtpoint/AutoOpenTestExtensionPoint.java @@ -0,0 +1,76 @@ +package org.pentaho.di.dataset.spoon.xtpoint; + +import org.pentaho.di.core.exception.KettleException; +import org.pentaho.di.core.extension.ExtensionPoint; +import org.pentaho.di.core.extension.ExtensionPointInterface; +import org.pentaho.di.core.logging.LogChannelInterface; +import org.pentaho.di.dataset.TransUnitTest; +import org.pentaho.di.dataset.spoon.DataSetHelper; +import org.pentaho.di.dataset.util.FactoriesHierarchy; +import org.pentaho.di.trans.TransMeta; +import org.pentaho.di.ui.core.dialog.EnterSelectionDialog; +import org.pentaho.di.ui.spoon.Spoon; + +import java.util.ArrayList; +import java.util.List; + +@ExtensionPoint( id = "AutoOpenTestExtensionPoint", + extensionPointId = "TransAfterOpen", + description = "Open the transformation unit test along with the transformation. Pick the one marked for auto opening." +) +public class AutoOpenTestExtensionPoint implements ExtensionPointInterface { + @Override public void callExtensionPoint( LogChannelInterface log, Object object ) throws KettleException { + + // The transformation that was just loaded + // + TransMeta transMeta = (TransMeta) object; + + // Running in Spoon... + // + Spoon spoon = Spoon.getInstance(); + DataSetHelper helper = DataSetHelper.getInstance(); + + // Get the list of unit tests for this one... + // + List tests = DataSetHelper.findTransformationUnitTest( transMeta, spoon.getMetaStore() ); + + // See which ones are auto opening... + // + List openTests = new ArrayList<>(); + tests.forEach( test -> { + if (test.isAutoOpening()) { + openTests.add(test); + } + }); + + // Nothing to see here, move along! + // + if (openTests.isEmpty()) { + return; + } + + // A single test, simply select it. + // + if (openTests.size()>=1) { + helper.getActiveTests().put( transMeta, openTests.get(0) ); + return; + } + + /* + // We have multiple tests, select which one... + // + String[] testNames = new String[openTests.size()]; + for (int i=0;i tests = findUnitTests( tge.getTransGraph().getTransMeta(), spoon.getMetaStore() ); + List tests = DataSetHelper.findTransformationUnitTest( tge.getTransGraph().getTransMeta(), spoon.getMetaStore() ); for ( final TransUnitTest test : tests ) { MenuItem testItem = new MenuItem( switchMenu, SWT.PUSH ); testItem.setText( test.getName() ); @@ -277,61 +277,6 @@ protected void switchUnitTest( TransUnitTest targetTest, TransMeta transMeta ) { DataSetHelper.getInstance().switchUnitTest( targetTest, transMeta ); } - private List findUnitTests( TransMeta transMeta, DelegatingMetaStore metaStore ) { - MetaStoreFactory factory = new MetaStoreFactory( TransUnitTest.class, metaStore, PentahoDefaults.NAMESPACE ); - List tests = new ArrayList(); - - - try { - - List allTests = factory.getElements(); - for ( TransUnitTest test : allTests ) { - // Match the filename - // - if ( StringUtils.isNotEmpty( transMeta.getFilename() ) ) { - - // What's the transformation absolute URI - // - FileObject transFile = KettleVFS.getFileObject( transMeta.getFilename() ); - String transUri = transFile.getName().getURI(); - - // What's the filename referenced in the test? - // - FileObject testTransFile = KettleVFS.getFileObject( test.calculateCompleteFilename(transMeta) ); - if (testTransFile.exists()) { - String testTransUri = testTransFile.getName().getURI(); - - if ( transUri.equals( testTransUri ) ) { - tests.add( test ); - } - } - } else { - if ( transMeta.getRepository() != null ) { - // No filename, check the object_id ... - // - if ( transMeta.getObjectId() != null && transMeta.getObjectId().getId().equals( test.getTransObjectId() ) ) { - tests.add( test ); - } else { - // Try the repository path.. - // - // What is the repsository path? - String repositoryPath = transMeta.getRepositoryDirectory().getPath() + "/" + transMeta.getName(); - if ( repositoryPath.equals( test.getTransRepositoryPath() ) ) { - tests.add( test ); - } - } - } - } - } - - } catch ( Exception exception ) { - new ErrorDialog( Spoon.getInstance().getShell(), - BaseMessages.getString( PKG, "ShowUnitTestMenuExtensionPoint.ErrorFindingUnitTestsForTransformation.Title" ), - BaseMessages.getString( PKG, "ShowUnitTestMenuExtensionPoint.ErrorFindingUnitTestsForTransformation.Message" ), - exception ); - } - return tests; - } /** * Find the canvas of TransGraph. For some reason it's not exposed. diff --git a/src/test/java/org/pentaho/di/dataset/TransUnitTestExecutionTest.java b/src/test/java/org/pentaho/di/dataset/TransUnitTestExecutionTest.java index 60e9987..0500efe 100644 --- a/src/test/java/org/pentaho/di/dataset/TransUnitTestExecutionTest.java +++ b/src/test/java/org/pentaho/di/dataset/TransUnitTestExecutionTest.java @@ -195,7 +195,7 @@ private void createUnitTest() { tweaks.add( new TransUnitTestTweak(TransTweak.REMOVE_STEP, "step3") ); unitTest = new TransUnitTest(UNIT_TEST_NAME, UNIT_TEST_DESCRIPTION, null, null, - "src/test/resources/simple-mapping.ktr", inputs, goldens, tweaks, TestType.UNIT_TEST, null, new ArrayList()); + "src/test/resources/simple-mapping.ktr", inputs, goldens, tweaks, TestType.UNIT_TEST, null, new ArrayList(), false); } public void testExecution() throws Exception { diff --git a/src/test/java/org/pentaho/di/dataset/TransUnitTestTest.java b/src/test/java/org/pentaho/di/dataset/TransUnitTestTest.java index 9fc50ed..59094cd 100644 --- a/src/test/java/org/pentaho/di/dataset/TransUnitTestTest.java +++ b/src/test/java/org/pentaho/di/dataset/TransUnitTestTest.java @@ -60,7 +60,8 @@ protected void setUp() throws Exception { goldens, tweaks, TestType.UNIT_TEST, - null, new ArrayList() + null, new ArrayList(), + false ); }