Skip to content

Commit aa90909

Browse files
closes #10 - Generate utPLSQL test for an object
package, type, function, procedure in navigator tree and in PL/SQL editor (when parser detects such an object)
1 parent 33abdf8 commit aa90909

File tree

4 files changed

+255
-0
lines changed

4 files changed

+255
-0
lines changed

sqldev/src/main/java/org/utplsql/sqldev/UtplsqlWorksheet.xtend

+8
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,12 @@ class UtplsqlWorksheet {
117117
thread.start
118118
}
119119
120+
def static void openWithCode(String code, String connectionName) {
121+
val worksheet = OpenWorksheetWizard.openNewTempWorksheet(connectionName, code) as Worksheet
122+
if (connectionName === null) {
123+
worksheet.comboConnection = null
124+
}
125+
WorksheetUtil.setWorksheetTabName(worksheet.context.node.URL, UtplsqlResources.getString("WORKSHEET_TITLE"))
126+
}
127+
120128
}

sqldev/src/main/java/org/utplsql/sqldev/menu/UtplsqlController.xtend

+79
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ import org.utplsql.sqldev.UtplsqlWorksheet
3737
import org.utplsql.sqldev.dal.UtplsqlDao
3838
import org.utplsql.sqldev.model.URLTools
3939
import org.utplsql.sqldev.model.preference.PreferenceModel
40+
import org.utplsql.sqldev.oddgen.TestTemplate
41+
import org.utplsql.sqldev.oddgen.model.GenContext
4042
import org.utplsql.sqldev.parser.UtplsqlParser
4143

4244
class UtplsqlController implements Controller {
@@ -52,6 +54,9 @@ class UtplsqlController implements Controller {
5254
if (action.commandId === UtplsqlController.UTLPLSQL_TEST_CMD_ID) {
5355
runTest(context)
5456
return true
57+
} else if (action.commandId === UtplsqlController.UTLPLSQL_GENERATE_CMD_ID) {
58+
generateTest(context)
59+
return true
5560
}
5661
return false
5762
}
@@ -188,6 +193,36 @@ class UtplsqlController implements Controller {
188193
logger.fine('''url: «url»''')
189194
return url
190195
}
196+
197+
private def void populateGenContext(GenContext genContext, PreferenceModel preferences) {
198+
genContext.generateFiles = preferences.generateFiles
199+
genContext.outputDirectory = preferences.outputDirectory
200+
genContext.testPackagePrefix = preferences.testPackagePrefix.toLowerCase
201+
genContext.testPackageSuffix = preferences.testPackageSuffix.toLowerCase
202+
genContext.testUnitPrefix = preferences.testUnitPrefix.toLowerCase
203+
genContext.testUnitSuffix = preferences.testUnitSuffix.toLowerCase
204+
genContext.numberOfTestsPerUnit = preferences.numberOfTestsPerUnit
205+
genContext.generateComments = preferences.generateComments
206+
genContext.disableTests = preferences.disableTests
207+
genContext.suitePath = preferences.suitePath.toLowerCase
208+
genContext.indentSpaces = preferences.indentSpaces
209+
}
210+
211+
private def getGenContext(Context context) {
212+
val connectionName = context.URL.connectionName
213+
val genContext = new GenContext
214+
if (Connections.instance.isConnectionOpen(connectionName)) {
215+
genContext.conn = Connections.instance.getConnection(connectionName)
216+
val element = context.selection.get(0)
217+
if (element instanceof PlSqlNode) {
218+
genContext.objectType = element.objectType.replace(" BODY", "")
219+
genContext.objectName = element.objectName
220+
val preferences = PreferenceModel.getInstance(Preferences.preferences)
221+
populateGenContext(genContext, preferences)
222+
}
223+
}
224+
return genContext
225+
}
191226

192227
def runTest(Context context) {
193228
val view = context.view
@@ -223,4 +258,48 @@ class UtplsqlController implements Controller {
223258
}
224259
}
225260
}
261+
262+
def generateTest(Context context) {
263+
val view = context.view
264+
val node = context.node
265+
logger.finer('''Generate utPLSQL test from view «view?.class?.name» and node «node?.class?.name».''')
266+
if (view instanceof Editor) {
267+
val component = view.defaultFocusComponent
268+
if (component instanceof JEditorPane) {
269+
var String connectionName = null;
270+
if (node instanceof DatabaseSourceNode) {
271+
connectionName = node.connectionName
272+
} else if (view instanceof Worksheet) {
273+
connectionName = view.connectionName
274+
}
275+
if (connectionName !== null) {
276+
if (Connections.instance.isConnectionOpen(connectionName)) {
277+
val genContext = new GenContext
278+
genContext.conn = Connections.instance.getConnection(connectionName)
279+
val parser = new UtplsqlParser(component.text)
280+
val position = component.caretPosition
281+
val obj = parser.getObjectAt(position)
282+
if (obj !== null) {
283+
genContext.objectType = obj.type.toUpperCase
284+
genContext.objectName = obj.name.toUpperCase
285+
val preferences = PreferenceModel.getInstance(Preferences.preferences)
286+
populateGenContext(genContext, preferences)
287+
val testTemplate = new TestTemplate(genContext)
288+
val code = testTemplate.generate.toString
289+
UtplsqlWorksheet.openWithCode(code, connectionName)
290+
}
291+
}
292+
}
293+
}
294+
295+
} else if (view instanceof DBNavigatorWindow) {
296+
val url=context.URL
297+
if (url !== null) {
298+
val connectionName = url.connectionName
299+
val testTemplate = new TestTemplate(context.genContext)
300+
val code = testTemplate.generate.toString
301+
UtplsqlWorksheet.openWithCode(code, connectionName)
302+
}
303+
}
304+
}
226305
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Copyright 2018 Philipp Salvisberg <philipp.salvisberg@trivadis.com>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.utplsql.sqldev.oddgen
17+
18+
import java.time.LocalDateTime
19+
import java.time.format.DateTimeFormatter
20+
import java.util.List
21+
import org.utplsql.sqldev.dal.UtplsqlDao
22+
import org.utplsql.sqldev.oddgen.model.GenContext
23+
24+
class TestTemplate {
25+
var GenContext context
26+
var UtplsqlDao dao
27+
var List<String> units
28+
var dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
29+
var today = dateTimeFormatter.format(LocalDateTime.now())
30+
31+
new(GenContext context) {
32+
this.context = context
33+
dao = new UtplsqlDao(context.conn)
34+
units = dao.units(context.objectType, context.objectName)
35+
}
36+
37+
def replaceTabsWithSpaces(CharSequence input) {
38+
val spaces = String.format("%1$"+context.indentSpaces+"s", "")
39+
return input.toString.replace("\t", spaces)
40+
}
41+
42+
def generateSpec() {
43+
val ret = '''
44+
«val objectName = context.objectName.toLowerCase»
45+
«val packageName = '''«context.testPackagePrefix»«objectName»«context.testPackageSuffix»'''»
46+
CREATE OR REPLACE PACKAGE «packageName» IS
47+
48+
«IF context.generateComments»
49+
/* generated by utPLSQL for SQL Developer on «today» */
50+
51+
«ENDIF»
52+
--%suite(«packageName»)
53+
«IF !context.suitePath.empty»
54+
--%suitepath(«context.suitePath»)
55+
«ENDIF»
56+
57+
«FOR u : units»
58+
«val unit = u.toLowerCase»
59+
«IF context.numberOfTestsPerUnit > 1 && (context.objectType == "PACKAGE" || context.objectType == "TYPE")»
60+
--%context(«unit»)
61+
62+
«ENDIF»
63+
«FOR i : 1 .. context.numberOfTestsPerUnit»
64+
--%test
65+
«IF context.disableTests»
66+
--%disabled
67+
«ENDIF»
68+
PROCEDURE «context.testUnitPrefix»«unit»«context.testUnitSuffix»«IF context.numberOfTestsPerUnit > 1»«i»«ENDIF»;
69+
70+
«ENDFOR»
71+
«IF context.numberOfTestsPerUnit > 1 && (context.objectType == "PACKAGE" || context.objectType == "TYPE")»
72+
--%endcontext
73+
74+
«ENDIF»
75+
«ENDFOR»
76+
END «packageName»;
77+
/
78+
'''
79+
return ret.replaceTabsWithSpaces
80+
}
81+
82+
def generateBody() {
83+
val ret = '''
84+
«val objectName = context.objectName.toLowerCase»
85+
CREATE OR REPLACE PACKAGE BODY «context.testPackagePrefix»«objectName»«context.testPackageSuffix» IS
86+
87+
«IF context.generateComments»
88+
/* generated by utPLSQL for SQL Developer on «today» */
89+
90+
«ENDIF»
91+
«FOR u : units»
92+
«val unit = u.toLowerCase»
93+
«FOR i : 1 .. context.numberOfTestsPerUnit»
94+
«val procedureName = '''«context.testUnitPrefix»«unit»«context.testUnitSuffix»«IF context.numberOfTestsPerUnit > 1»«i»«ENDIF»'''»
95+
«IF context.generateComments»
96+
--
97+
-- test «unit»«IF context.numberOfTestsPerUnit > 0» case «i»: ...«ENDIF»
98+
--
99+
«ENDIF»
100+
PROCEDURE «procedureName» IS
101+
l_actual INTEGER := 0;
102+
l_expected INTEGER := 1;
103+
BEGIN
104+
«IF context.generateComments»
105+
-- populate actual
106+
-- «objectName».«unit»;
107+
108+
-- populate expected
109+
-- ...
110+
111+
-- assert
112+
«ENDIF»
113+
ut.expect(l_actual).to_equal(l_expected);
114+
END «procedureName»;
115+
116+
«ENDFOR»
117+
«ENDFOR»
118+
119+
END «context.testPackagePrefix»«objectName»«context.testPackageSuffix»;
120+
/
121+
'''
122+
return ret.replaceTabsWithSpaces
123+
}
124+
125+
def generate() '''
126+
«generateSpec»
127+
128+
«generateBody»
129+
'''
130+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2018 Philipp Salvisberg <philipp.salvisberg@trivadis.com>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.utplsql.sqldev.oddgen.model
17+
18+
import java.sql.Connection
19+
import org.eclipse.xtend.lib.annotations.Accessors
20+
import org.utplsql.sqldev.model.AbstractModel
21+
22+
@Accessors
23+
class GenContext extends AbstractModel {
24+
Connection conn
25+
String objectType
26+
String objectName
27+
boolean generateFiles
28+
String outputDirectory
29+
String testPackagePrefix
30+
String testPackageSuffix
31+
String testUnitPrefix
32+
String testUnitSuffix
33+
int numberOfTestsPerUnit
34+
boolean generateComments
35+
boolean disableTests
36+
String suitePath
37+
int indentSpaces
38+
}

0 commit comments

Comments
 (0)