diff --git a/sqldev/src/main/java/org/utplsql/sqldev/model/XMLTools.xtend b/sqldev/src/main/java/org/utplsql/sqldev/model/XMLTools.xtend
index de07c01e..5126486a 100644
--- a/sqldev/src/main/java/org/utplsql/sqldev/model/XMLTools.xtend
+++ b/sqldev/src/main/java/org/utplsql/sqldev/model/XMLTools.xtend
@@ -14,6 +14,11 @@
  */
 package org.utplsql.sqldev.model
 
+import java.io.StringWriter
+import javax.xml.transform.OutputKeys
+import javax.xml.transform.TransformerFactory
+import javax.xml.transform.dom.DOMSource
+import javax.xml.transform.stream.StreamResult
 import javax.xml.xpath.XPathConstants
 import javax.xml.xpath.XPathFactory
 import org.w3c.dom.Node
@@ -34,4 +39,29 @@ class XMLTools {
 		val Node node = expr.evaluate(doc, XPathConstants.NODE) as Node
 		return node 
 	}
-}
\ No newline at end of file
+	
+	def void trimWhitespace(Node node) {
+		val children = node.childNodes
+		for (i : 0 ..< children.length) {
+			val child = children.item(i)
+			if (child.nodeType == Node.TEXT_NODE) {
+				child.textContent = child.textContent.trim
+			}
+			trimWhitespace(child);
+		}
+	}
+	
+	def nodeToString(Node node, String cdataSectionElements) {
+		node.trimWhitespace
+		val writer = new StringWriter()
+		val factory = TransformerFactory.newInstance().newTransformer()
+		factory.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")
+		factory.setOutputProperty(OutputKeys.INDENT, "yes")
+		factory.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "3");
+		factory.setOutputProperty(OutputKeys.CDATA_SECTION_ELEMENTS, cdataSectionElements)
+		factory.transform(new DOMSource(node), new StreamResult(writer))
+		val result = writer.toString()
+		val fixedResult = result.replaceAll('''<!\[CDATA\[\s*\]\]>''',"")
+		return fixedResult
+	}
+}
diff --git a/sqldev/src/main/java/org/utplsql/sqldev/snippet/SnippetMerger.xtend b/sqldev/src/main/java/org/utplsql/sqldev/snippet/SnippetMerger.xtend
new file mode 100644
index 00000000..af3a7bb7
--- /dev/null
+++ b/sqldev/src/main/java/org/utplsql/sqldev/snippet/SnippetMerger.xtend
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2019 Philipp Salvisberg <philipp.salvisberg@trivadis.com>
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.utplsql.sqldev.snippet
+
+import java.io.BufferedReader
+import java.io.File
+import java.io.IOException
+import java.io.InputStreamReader
+import java.io.StringReader
+import java.nio.charset.Charset
+import java.nio.file.Files
+import java.nio.file.Paths
+import java.util.stream.Collectors
+import javax.xml.parsers.DocumentBuilderFactory
+import oracle.dbtools.util.Resource
+import org.utplsql.sqldev.model.XMLTools
+import org.xml.sax.InputSource
+
+class SnippetMerger {
+	val extension XMLTools xmlTools = new XMLTools
+	File userSnippetsFile 
+	String utplsqlSnippets 
+
+	def getUtplsqlSnippetsAsString() throws IOException {
+		val stream = class.getResourceAsStream("/org/utplsql/sqldev/resources/UtplsqlSnippets.xml")
+		val reader = new BufferedReader(new InputStreamReader(stream, Charset.defaultCharset))
+		return reader.lines.collect(Collectors.joining(System.lineSeparator))
+	}
+	
+	new() {
+		// works in SQL Developer only, otherwise a ExceptionInInitializerError is thrown
+		this (new File(Resource.RAPTOR_USER.absolutePath + File.separator + "UserSnippets.xml"))
+	}
+	
+	new(File file) {
+		utplsqlSnippets = utplsqlSnippetsAsString 
+		userSnippetsFile = file		
+	}
+	
+	def merge() {
+		var String result
+		if (userSnippetsFile.exists) {
+			// file exists, proper merge required
+			val userSnippets = new String(Files.readAllBytes(Paths.get(userSnippetsFile.absolutePath)))
+			val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
+			val	userSnippetsDoc = docBuilder.parse(new InputSource(new StringReader(userSnippets)))
+			val userSnippetsGroups = userSnippetsDoc.getNodeList('''/snippets/group[not(@category="utPLSQL Annotations" or @category="utPLSQL Expectations")]''')
+			val	utplsqlSnippetsDoc = docBuilder.parse(new InputSource(new StringReader(utplsqlSnippets)))
+			val utplsqlSnippetsGroups = utplsqlSnippetsDoc.getNodeList('''/snippets/group''')			
+			result = '''
+				<?xml version = '1.0' encoding = 'UTF-8'?>
+				<snippets>
+				   «FOR i : 0 ..< userSnippetsGroups.length»
+				      «userSnippetsGroups.item(i).nodeToString("code")»
+				   «ENDFOR»
+				   «FOR i : 0 ..< utplsqlSnippetsGroups.length»
+				      «utplsqlSnippetsGroups.item(i).nodeToString("code")»
+				   «ENDFOR»
+				</snippets>
+			'''
+		} else {
+			// just copy
+			result = utplsqlSnippets
+			
+		}
+		Files.write(Paths.get(userSnippetsFile.absolutePath), result.bytes)
+	}
+	
+	def getTemplate() {
+		return utplsqlSnippets
+	}
+	
+	def getFile() {
+		return userSnippetsFile
+	}
+	
+}
\ No newline at end of file
diff --git a/sqldev/src/main/java/org/utplsql/sqldev/ui/preference/PreferencePanel.xtend b/sqldev/src/main/java/org/utplsql/sqldev/ui/preference/PreferencePanel.xtend
index 9633fac0..9425bb98 100644
--- a/sqldev/src/main/java/org/utplsql/sqldev/ui/preference/PreferencePanel.xtend
+++ b/sqldev/src/main/java/org/utplsql/sqldev/ui/preference/PreferencePanel.xtend
@@ -20,6 +20,7 @@ import java.awt.event.ActionListener
 import java.util.Map
 import javax.swing.JButton
 import javax.swing.JCheckBox
+import javax.swing.JOptionPane
 import javax.swing.JPanel
 import javax.swing.JSpinner
 import javax.swing.JTabbedPane
@@ -33,6 +34,7 @@ import oracle.ide.panels.TraversalException
 import oracle.javatools.ui.layout.FieldLayoutBuilder
 import org.utplsql.sqldev.model.preference.PreferenceModel
 import org.utplsql.sqldev.resources.UtplsqlResources
+import org.utplsql.sqldev.snippet.SnippetMerger
 import org.utplsql.sqldev.ui.common.DirectoryChooser
 
 class PreferencePanel extends DefaultTraversablePanel {
@@ -43,6 +45,7 @@ class PreferencePanel extends DefaultTraversablePanel {
 	val JCheckBox clearScreenCheckBox = new JCheckBox
 	val JCheckBox autoExecuteCheckBox = new JCheckBox
 	val JCheckBox checkRunUtplsqlTestCheckBox = new JCheckBox
+	val JButton importSnippetsButton = new JButton(UtplsqlResources.getString("PREF_IMPORT_SNIPPETS_BUTTON_LABEL"))
 	val JPanel realtimeReporterPanel = new JPanel
 	val SpinnerNumberModel numberOfRunsInHistoryModel = new SpinnerNumberModel(1, 1, 100, 1);
 	val JSpinner numberOfRunsInHistorySpinner = new JSpinner(numberOfRunsInHistoryModel);
@@ -101,6 +104,7 @@ class PreferencePanel extends DefaultTraversablePanel {
 		runTab.add(
 			runTab.field.label.withText(UtplsqlResources.getString("PREF_CHECK_RUN_UTPLSQL_TEST_LABEL")).component(
 				checkRunUtplsqlTestCheckBox))
+		runTab.addRow(importSnippetsButton)
 		runTab.addVerticalSpring
 		
 		// realtime reporter group
@@ -200,6 +204,13 @@ class PreferencePanel extends DefaultTraversablePanel {
 		builder.addVerticalField("", tabbedPane)
 		builder.addVerticalSpring
 		
+		// register action listener for import snippets button 
+		importSnippetsButton.addActionListener(new ActionListener() {
+			override actionPerformed(ActionEvent event) {
+				importSnippets
+			}			
+		})
+		
 		// register action listener for create code template button 
 		createCodeTemplatesButton.addActionListener(new ActionListener() {
 			override actionPerformed(ActionEvent event) {
@@ -216,6 +227,15 @@ class PreferencePanel extends DefaultTraversablePanel {
 		})		
 	}
 	
+	private def importSnippets() {
+		val snippetMerger = new SnippetMerger
+		snippetMerger.merge
+		val file = snippetMerger.file.absolutePath
+		val message = String.format(UtplsqlResources.getString("PREF_CONFIRM_IMPORT_MESSAGE"), file)
+		JOptionPane.showMessageDialog(null, message, UtplsqlResources.getString("PREF_CONFIRM_IMPORT_TITLE"),
+			JOptionPane.INFORMATION_MESSAGE);
+	}
+	
 	private def loadCodeTemplates() {
 		val Map<String, String> map = CodeTemplateUtil.loadFiles()
 		for (key : map.keySet) {
diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties
index 2cf4c1f8..8d12bcc5 100644
--- a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties
+++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources.properties
@@ -31,6 +31,7 @@ PREF_RESET_PACKAGE_LABEL=Reset package before running utPLSQL?
 PREF_CLEAR_SCREEN_LABEL=Clear script output panel before running utPLSQL?
 PREF_AUTO_EXECUTE_LABEL=Execute unit test automatically?
 PREF_CHECK_RUN_UTPLSQL_TEST_LABEL=Check availability of menu option?
+PREF_IMPORT_SNIPPETS_BUTTON_LABEL=Import Snippets
 MENU_REALTIME_REPORTER_LABEL=Realtime Reporter
 PREF_NUMBER_OF_RUNS_IN_HISTORY_LABEL=Number of runs in history
 PREF_SHOW_DISABLED_COUNTER_LABEL=Show disabled counter?
@@ -56,6 +57,8 @@ PREF_GENERATE_FILES_LABEL=Generate files?
 PREF_OUTPUT_DIRECTORY_LABEL=Output directory
 PREF_OUTPUT_DIRECTORY_BUTTON_LABEL=Browse
 PREF_DELETE_EXISTING_FILES_LABEL=Delete existing files in output directory?
+PREF_CONFIRM_IMPORT_TITLE=Snippets imported
+PREF_CONFIRM_IMPORT_MESSAGE=Snippets imported into %s. Please restart SQL Developer for this change to take effect.
 MENU_RUN_TEST_LABEL=Run utPLSQL test
 MENU_CODE_COVERAGE_LABEL=Code coverage...
 MENU_GENERATE_TEST_LABEL=Generate utPLSQL test
diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties
index d80965a5..eb86a295 100644
--- a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties
+++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlResources_de.properties
@@ -8,6 +8,7 @@ PREF_RESET_PACKAGE_LABEL=Package vor der Ausf
 PREF_CLEAR_SCREEN_LABEL=Skriptausgabe-Fenster vor der Ausf�hrung von utPLSQL leeren?
 PREF_AUTO_EXECUTE_LABEL=Unit Test automatisch ausf�hren?
 PREF_CHECK_RUN_UTPLSQL_TEST_LABEL=Verf�gbarkeit der Men�option pr�fen?
+PREF_IMPORT_SNIPPETS_BUTTON_LABEL=Code-Schnipsel importieren
 MENU_REALTIME_REPORTER_LABEL=Realtime Reporter
 PREF_NUMBER_OF_RUNS_IN_HISTORY_LABEL=Anzahl Ausf�hrungen in der Historie
 PREF_SHOW_DISABLED_COUNTER_LABEL=Deaktiviert-Z�hler  anzeigen?
@@ -33,6 +34,8 @@ PREF_GENERATE_FILES_LABEL=Dateien generieren?
 PREF_OUTPUT_DIRECTORY_LABEL=Ausgabeverzeichnis
 PREF_OUTPUT_DIRECTORY_BUTTON_LABEL=Ausw�hlen
 PREF_DELETE_EXISTING_FILES_LABEL=Bestehende Dateien im Ausgabeverzeichnis l�schen?
+PREF_CONFIRM_IMPORT_TITLE=Code-Schnipsel importiert
+PREF_CONFIRM_IMPORT_MESSAGE=Code-Schnipsel in %s importiert. Bitte starten Sie den SQL Developer neu, um diese �nderung zu aktivieren.
 MENU_RUN_TEST_LABEL=utPLSQL Test ausf�hren
 MENU_CODE_COVERAGE_LABEL=Codeabdeckung...
 MENU_GENERATE_TEST_LABEL=utPLSQL Test generieren
diff --git a/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlSnippets.xml b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlSnippets.xml
new file mode 100644
index 00000000..8915628f
--- /dev/null
+++ b/sqldev/src/main/resources/org/utplsql/sqldev/resources/UtplsqlSnippets.xml
@@ -0,0 +1,262 @@
+<?xml version = '1.0' encoding = 'UTF-8'?>
+<snippets>
+   <group category="utPLSQL Annotations" language="PLSQL">
+      <snippet name="suite" description="Package level. Mandatory. Marks package as a test suite. Optional suite description can be provided (see displayname).">
+         <code>
+            <![CDATA[--%suite(<description>)]]>
+         </code>
+      </snippet>
+      <snippet name="suitepath" description="Package level. Similar to java package. The annotation allows logical grouping of suites into hierarchies.">
+         <code>
+            <![CDATA[--%suitepath(<path>)]]>
+         </code>
+      </snippet>
+      <snippet name="displayname" description="Package/procedure leve. Human-readable and meaningful description of a context/suite/test. Provides description to a context when used within context. When used with test or suite annotation, overrides the &lt;description> provided with suite/test.">
+         <code>
+            <![CDATA[--%displayname(<description>)]]>
+         </code>
+      </snippet>
+      <snippet name="test" description="Procedure level. Denotes that the annotated procedure is a unit test procedure. Optional test description can by provided (see displayname).">
+         <code>
+            <![CDATA[--%test(<description>)]]>
+         </code>
+      </snippet>
+      <snippet name="throws" description="Procedure level. Denotes that the annotated test procedure must throw one of the exceptions provided. Supported forms of exceptions are: numeric literals, numeric contant names, exception constant names, predefined Oracle exception names.">
+         <code>
+            <![CDATA[--%throws(<exception>[,...])]]>
+         </code>
+      </snippet>
+      <snippet name="beforeall" description="Procedure level. Denotes that the annotated procedure should be executed once before all elements of the suite.">
+         <code>
+            <![CDATA[--%beforeall]]>
+         </code>
+      </snippet>
+      <snippet name="afterall" description="Procedure level. Denotes that the annotated procedure should be executed once after all elements of the suite.">
+         <code>
+            <![CDATA[--%afterall]]>
+         </code>
+      </snippet>
+      <snippet name="beforeeach" description="Procedure level. &#x9;Denotes that the annotated procedure should be executed before each %test procedure in the suite.">
+         <code>
+            <![CDATA[--%beforeeach]]>
+         </code>
+      </snippet>
+      <snippet name="aftereach" description="&#x9;Procedure level. Denotes that the annotated procedure should be executed after each %test procedure in the suite.">
+         <code>
+            <![CDATA[--%aftereach]]>
+         </code>
+      </snippet>
+      <snippet name="beforeall package level" description="Package level. Denotes that the mentioned procedure(s) should be executed once before all elements of the suite.">
+         <code>
+            <![CDATA[--%beforeall([[<owner>.]<package>.]<procedure>[,...])]]>
+         </code>
+      </snippet>
+      <snippet name="afterall package level" description="Package level. &#x9;Denotes that the mentioned procedure(s) should be executed once after all elements of the suite.">
+         <code>
+            <![CDATA[--%afterall([[<owner>.]<package>.]<procedure>[,...])]]>
+         </code>
+      </snippet>
+      <snippet name="beforeeach package level" description="Package level. Denotes that the mentioned procedure(s) should be executed before each %test procedure in the suite.">
+         <code>
+            <![CDATA[--%beforeeach([[<owner>.]<package>.]<procedure>[,...])]]>
+         </code>
+      </snippet>
+      <snippet name="aftereach package level" description="Package level. Denotes that the mentioned procedure(s) should be executed after each %test procedure in the suite.">
+         <code>
+            <![CDATA[--%aftereach([[<owner>.]<package>.]<procedure>[,...])]]>
+         </code>
+      </snippet>
+      <snippet name="beforetest" description="Procedure level. Denotes that mentioned procedure(s) should be executed before the annotated %test procedure.">
+         <code>
+            <![CDATA[--%beforetest([[<owner>.]<package>.]<procedure>[,...])]]>
+         </code>
+      </snippet>
+      <snippet name="aftertest" description="Procedure level. Denotes that mentioned procedure(s) should be executed after the annotated %test procedure">
+         <code>
+            <![CDATA[--%aftertest([[<owner>.]<package>.]<procedure>[,...])]]>
+         </code>
+      </snippet>
+      <snippet name="rollback" description="Package/procedure level. Defines transaction control. Supported values: auto(default) - a savepoint is created before invocation of each “before block” is and a rollback to specific savepoint is issued after each “after” block; manual - rollback is never issued automatically">
+         <code>
+            <![CDATA[--%rollback(<type>)]]>
+         </code>
+      </snippet>
+      <snippet name="disabled" description="Package/procedure level. Used to disable a suite or a test. Disabled suites/tests do not get executed, they are however marked and reported as disabled in a test run.">
+         <code>
+            <![CDATA[--%disabled]]>
+         </code>
+      </snippet>
+      <snippet name="context" description="Package level. Denotes start of a named context (sub-suite) in a suite package">
+         <code>
+            <![CDATA[--%context(<name>)]]>
+         </code>
+      </snippet>
+      <snippet name="endcontext" description="Package level. Denotes end of a nested context (sub-suite) in a suite package">
+         <code>
+            <![CDATA[--%endcontext]]>
+         </code>
+      </snippet>
+      <snippet name="tags" description="Package/procedure level. Used to label a test or a suite for purpose of identification">
+         <code>
+            <![CDATA[--%tags]]>
+         </code>
+      </snippet>
+   </group>
+   <group category="utPLSQL Expectations" language="PLSQL">
+      <snippet name="be_between" description="Validates that the actual value is between the lower and upper bound.">
+         <code>
+            <![CDATA[ut.expect(n1).to_be_between(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="be_empty" description="Unary matcher that validates if the provided dataset is empty">
+         <code>
+            <![CDATA[ut.expect(n).to_be_empty();]]>
+         </code>
+      </snippet>
+      <snippet name="be_false" description="Unary matcher that validates if the provided value is false.">
+         <code>
+            <![CDATA[ut.expect(n).to_be_false();]]>
+         </code>
+      </snippet>
+      <snippet name="be_greater_or_equal" description="Checks if the actual value is greater or equal than the expected.">
+         <code>
+            <![CDATA[ut.expect(n1).to_be_greater_or_equal(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="be_greater_than" description="Checks if the actual value is greater than the expected.">
+         <code>
+            <![CDATA[ut.expect(n1).to_be_greater_than(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="be_less_or_equal" description="Checks if the actual value is less or equal than the expected.">
+         <code>
+            <![CDATA[ut.expect(n1).to_be_less_or_equal(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="be_less_than" description="Checks if the actual value is less than the expected.">
+         <code>
+            <![CDATA[ut.expect(n1).to_be_less_than(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="be_like" description="Validates that the actual value is like the expected expression.">
+         <code>
+            <![CDATA[ut.expect(n1).to_be_like(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="be_not_null" description="Unary matcher that validates if the actual value is not null.">
+         <code>
+            <![CDATA[ut.expect(n).to_be_not_null();]]>
+         </code>
+      </snippet>
+      <snippet name="be_null" description="Unary matcher that validates if the actual value is null.">
+         <code>
+            <![CDATA[ut.expect(n).to_be_null();]]>
+         </code>
+      </snippet>
+      <snippet name="be_true" description="Unary matcher that validates if the provided value is true.">
+         <code>
+            <![CDATA[ut.expect(n).to_be_true();]]>
+         </code>
+      </snippet>
+      <snippet name="have_count" description="Unary matcher that validates if the provided dataset count is equal to expected value.">
+         <code>
+            <![CDATA[ut.expect(n1).to_have_count(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="match" description="Validates that the actual value is matching the expected regular expression.">
+         <code>
+            <![CDATA[ut.expect(n1).to_match(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="equal" description="Validate that actual value is equal to expected">
+         <code>
+            <![CDATA[ut.expect(n1).to_equal(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="contain" description="This matcher supports only compound data comparison. It check if the give set contain all values from given subset.">
+         <code>
+            <![CDATA[ut.expect(n1).to_contain(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="not_to_be_empty" description="Unary matcher that validates if the provided dataset is not empty">
+         <code>
+            <![CDATA[ut.expect(n).not_to_be_empty();]]>
+         </code>
+      </snippet>
+      <snippet name="not_to_be_false" description="Unary matcher that validates if the provided value is not false.">
+         <code>
+            <![CDATA[ut.expect(n).not_to_be_false();]]>
+         </code>
+      </snippet>
+      <snippet name="not_to_be_greater_or_equal" description="Checks if the actual value is not greater or equal than the expected.">
+         <code>
+            <![CDATA[ut.expect(n1).not_to_be_greater_or_equal(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="not_to_be_greater_than" description="Checks if the actual value is not greater than the expected.">
+         <code>
+            <![CDATA[ut.expect(n1).not_to_be_greater_than(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="not_to_be_less_or_equal" description="Checks if the actual value is not less or equal than the expected.">
+         <code>
+            <![CDATA[ut.expect(n1).not_to_be_less_or_equal(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="not_to_be_less_than" description="Checks if the actual value is not less than the expected.">
+         <code>
+            <![CDATA[ut.expect(n1).not_to_be_less_than(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="not_to_be_like" description="Validates that the actual value is not like the expected expression.">
+         <code>
+            <![CDATA[ut.expect(n1).not_to_be_like(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="not_to_have_count" description="Unary matcher that validates if the provided dataset count is not equal to expected value.">
+         <code>
+            <![CDATA[ut.expect(n1).not_to_have_count(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="not_to_match" description="Validates that the actual value is not matching the expected regular expression.">
+         <code>
+            <![CDATA[ut.expect(n1).not_to_match(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="not_to_equal" description="Validate that actual value is not equal to expected">
+         <code>
+            <![CDATA[ut.expect(n1).not_to_equal(n2);]]>
+         </code>
+      </snippet>
+      <snippet name="not_to_contain" description="This matcher supports only compound data comparison. It check if the give set not contain all values from given subset.">
+         <code>
+            <![CDATA[ut.expect(n1).not_to_contain(n2);]]>
+         </code>
+      </snippet>
+      <snippet name=".include" description="Valid only for compound data types. Item, comma separated list of items or table of items to include">
+         <code>
+            <![CDATA[.include(n)]]>
+         </code>
+      </snippet>
+      <snippet name=".exclude" description="Valid only for compound data types. Item, comma separated list of items or table of items to exclude">
+         <code>
+            <![CDATA[.exclude(n)]]>
+         </code>
+      </snippet>
+      <snippet name=".unordered" description="Valid only for compound data types.ignore order of data sets when comparing data. Default when comparing data-sets with to_contain">
+         <code>
+            <![CDATA[.unordered]]>
+         </code>
+      </snippet>
+      <snippet name=".join_by" description="Valid only for compound data types. Item, comma separated list of items or table of items to join by two cursors">
+         <code>
+            <![CDATA[.join_by(n)]]>
+         </code>
+      </snippet>
+      <snippet name=".unordered_columns" description="Valid only for compound data types. Ignore the ordering of columns / attributes in compared data-sets. Column/attribute names will be used to identify data to be compared and the position will be ignored.">
+         <code>
+            <![CDATA[.unordered_columns]]>
+         </code>
+      </snippet>
+   </group>
+</snippets>
diff --git a/sqldev/src/test/java/org/utplsql/sqldev/test/SnippetTest.xtend b/sqldev/src/test/java/org/utplsql/sqldev/test/SnippetTest.xtend
new file mode 100644
index 00000000..1a7e2387
--- /dev/null
+++ b/sqldev/src/test/java/org/utplsql/sqldev/test/SnippetTest.xtend
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2019 Philipp Salvisberg <philipp.salvisberg@trivadis.com>
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.utplsql.sqldev.test
+
+import java.io.File
+import java.nio.file.Files
+import java.nio.file.Paths
+import org.junit.Assert
+import org.junit.Test
+import org.utplsql.sqldev.snippet.SnippetMerger
+
+class SnippetTest {
+
+	@Test
+	def void mergeAsCopy() {
+		val file = new File(System.getProperty("user.home") + File.separator + "UserSnippets.xml")
+		file.delete
+		val merger = new SnippetMerger(file)
+		merger.merge
+		Assert.assertTrue(file.exists)
+		val userSnippetsXml = new String(Files.readAllBytes(Paths.get(file.absolutePath)))
+		Assert.assertEquals(merger.template, userSnippetsXml )
+	}
+
+	@Test
+	def void mergeKeepExisting() {
+		val file = new File(System.getProperty("user.home") + File.separator + "UserSnippets.xml")
+		file.delete
+		val userSnippetsXml = '''
+			<?xml version = '1.0' encoding = 'UTF-8'?>
+			<snippets>
+			   <group category="utPLSQL" language="PLSQL">
+			      <snippet name="test s" description="test s">
+			         <code>
+			            <![CDATA[bla bla bla]]>
+			         </code>
+			      </snippet>
+			   </group>
+			</snippets>
+		'''.toString
+		Files.write(Paths.get(file.absolutePath), userSnippetsXml.bytes)
+		val merger = new SnippetMerger(file)
+		merger.merge
+		Assert.assertTrue(file.exists)
+		val userSnippetsXml2 = new String(Files.readAllBytes(Paths.get(file.absolutePath)))
+		Assert.assertTrue(userSnippetsXml2.length > userSnippetsXml.length)
+		Assert.assertTrue(userSnippetsXml2.contains('''<group category="utPLSQL" language="PLSQL">'''))
+		Assert.assertTrue(userSnippetsXml2.contains('''<group category="utPLSQL Annotations" language="PLSQL">'''))
+		Assert.assertTrue(userSnippetsXml2.contains('''<group category="utPLSQL Expectations" language="PLSQL">'''))
+	} 
+
+	@Test
+	def void mergeRemoveExisting() {
+		val file = new File(System.getProperty("user.home") + File.separator + "UserSnippets.xml")
+		file.delete
+		val userSnippetsXml = '''
+			<?xml version = '1.0' encoding = 'UTF-8'?>
+			<snippets>
+			   <group category="utPLSQL Annotations" language="XYZ"/>
+			   <group category="utPLSQL Expectations" language="XYZ"/>
+			</snippets>
+		'''.toString
+		Files.write(Paths.get(file.absolutePath), userSnippetsXml.bytes)
+		val merger = new SnippetMerger(file)
+		merger.merge
+		Assert.assertTrue(file.exists)
+		val userSnippetsXml2 = new String(Files.readAllBytes(Paths.get(file.absolutePath)))
+		Assert.assertTrue(userSnippetsXml2.length > userSnippetsXml.length)
+		Assert.assertFalse(userSnippetsXml2.contains('''<group category="utPLSQL Annotations" language="XYZ">'''))
+		Assert.assertFalse(userSnippetsXml2.contains('''<group category="utPLSQL Expectations" language="XYZ">'''))
+		Assert.assertTrue(userSnippetsXml2.contains('''<group category="utPLSQL Annotations" language="PLSQL">'''))
+		Assert.assertTrue(userSnippetsXml2.contains('''<group category="utPLSQL Expectations" language="PLSQL">'''))
+	} 
+
+
+}