├── .0pdd.yml ├── .gitattributes ├── .github └── workflows │ └── quality-pipeline.yaml ├── .gitignore ├── .rultor.yml ├── .workflows ├── amend-work-after ├── amend-work-ahead ├── save-work-after └── save-work-ahead ├── LICENSE ├── README.md ├── build.gradle ├── docs ├── Makefile ├── conf.py ├── index.rst ├── make.bat ├── md │ ├── artifacts.md │ ├── concept.md │ ├── entry-points.md │ └── getting-started.md └── requirements.txt ├── gradle.properties ├── gradle ├── bintray.gradle ├── jacoco.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── scrt ├── gradle.properties.asc └── secring.gpg.asc ├── settings.gradle ├── sunshine-core-deps ├── build.gradle └── src │ └── main │ └── java │ └── org │ └── tatools │ └── testng │ ├── DisabledTest.java │ ├── FailedTest.java │ ├── PassedTest.java │ ├── SkippedTest.java │ ├── Test1.java │ └── package-info.java ├── sunshine-core ├── build.gradle ├── gradle.properties └── src │ ├── main │ └── java │ │ └── org │ │ └── tatools │ │ └── sunshine │ │ └── core │ │ ├── CompositeStatus.java │ │ ├── Condition.java │ │ ├── Directory.java │ │ ├── DirectoryBase.java │ │ ├── DirectorySafe.java │ │ ├── DirectoryWithAutomaticCreation.java │ │ ├── DirectoryWithAutomaticDeletion.java │ │ ├── File.java │ │ ├── FileBase.java │ │ ├── FileSystem.java │ │ ├── FileSystemException.java │ │ ├── FileSystemFiltered.java │ │ ├── FileSystemOfClasses.java │ │ ├── FileSystemOfClasspathClasses.java │ │ ├── FileSystemOfFileSystems.java │ │ ├── FileSystemOfJarFile.java │ │ ├── FileSystemOfJarFiles.java │ │ ├── FileSystemOfPath.java │ │ ├── FileSystemPath.java │ │ ├── FileSystemPathBase.java │ │ ├── FileSystemPathRelative.java │ │ ├── Kernel.java │ │ ├── KernelException.java │ │ ├── RegexCondition.java │ │ ├── SequentialExecution.java │ │ ├── Star.java │ │ ├── Status.java │ │ ├── Suite.java │ │ ├── SuiteException.java │ │ ├── SuiteFromClasses.java │ │ ├── SuiteFromFileSystem.java │ │ ├── Sun.java │ │ ├── SunshineException.java │ │ ├── SunshineSuite.java │ │ ├── SunshineSuiteFilterable.java │ │ ├── SunshineSuitePrintable.java │ │ ├── SunshineTest.java │ │ ├── Test.java │ │ ├── TestException.java │ │ ├── TestFromClass.java │ │ ├── TestFromFile.java │ │ ├── VerboseRegex.java │ │ └── package-info.java │ └── test │ └── java │ └── org │ └── tatools │ └── sunshine │ └── core │ ├── CompositeStatusTest.java │ ├── DirectoryBaseTest.java │ ├── DirectoryWithAutomaticCreationTest.java │ ├── DirectoryWithAutomaticDeletionTest.java │ ├── FileBaseTest.java │ ├── FileSystemFilteredTest.java │ ├── FileSystemOfClassesTest.java │ ├── FileSystemOfClasspathClassesTest.java │ ├── FileSystemOfFileSystemsTest.java │ ├── FileSystemOfJarFileTest.java │ ├── FileSystemOfJarFilesTest.java │ ├── FileSystemOfPathTest.java │ ├── FileSystemPathBaseTest.java │ ├── FileSystemPathRelativeTest.java │ ├── RegexConditionTest.java │ ├── SequentialExecutionTest.java │ ├── SuiteFromClassesTest.java │ ├── SuiteFromFileSystemTest.java │ ├── SunTest.java │ ├── SunshineSuitePrintableTest.java │ ├── TestFromClassTest.java │ ├── TestFromFileTest.java │ └── VerboseRegexTest.java ├── sunshine-junit4-integration-tests ├── build.gradle └── src │ └── main │ └── java │ └── org │ └── tatools │ └── junit4tests │ ├── PassedTest.java │ └── package-info.java ├── sunshine-junit4 ├── build.gradle ├── gradle.properties └── src │ ├── main │ └── java │ │ └── org │ │ └── tatools │ │ └── sunshine │ │ └── junit4 │ │ ├── Junit4Kernel.java │ │ ├── JunitStatus.java │ │ ├── JunitSuite.java │ │ ├── Sunshine.java │ │ └── package-info.java │ └── test │ └── java │ └── org │ └── tatools │ └── sunshine │ └── junit4 │ ├── Junit4KernelTest.java │ ├── JunitStatusTest.java │ └── JunitSuiteTest.java ├── sunshine-junit5-integration-tests ├── build.gradle └── src │ └── main │ └── java │ └── org │ └── tatools │ └── junit5tests │ ├── PassedTest.java │ └── package-info.java ├── sunshine-junit5 ├── build.gradle ├── gradle.properties └── src │ ├── main │ └── java │ │ └── org │ │ └── tatools │ │ └── sunshine │ │ └── junit5 │ │ ├── Junit5Kernel.java │ │ ├── Junit5Status.java │ │ ├── Sunshine.java │ │ └── package-info.java │ └── test │ └── java │ └── org │ └── tatools │ └── sunshine │ └── junit5 │ ├── Junit5KernelTest.java │ └── Junit5StatusTest.java ├── sunshine-testng-integration-tests ├── build.gradle └── src │ └── main │ ├── java │ └── org │ │ └── tatools │ │ └── testngtests │ │ ├── PassedTest.java │ │ ├── TestNGXmlTest1.java │ │ ├── TestNGXmlTest2.java │ │ └── package-info.java │ └── resources │ ├── testng.xml │ └── testng.yaml ├── sunshine-testng ├── build.gradle ├── gradle.properties └── src │ ├── main │ └── java │ │ └── org │ │ └── tatools │ │ └── sunshine │ │ └── testng │ │ ├── LoadableTestNGSuite.java │ │ ├── PreparedTestNGSuite.java │ │ ├── Sunshine.java │ │ ├── SunshineTestNG.java │ │ ├── TestNGKernel.java │ │ ├── TestNGStatus.java │ │ ├── TestNGSuite.java │ │ ├── TestNGTest.java │ │ └── package-info.java │ └── test │ ├── java │ └── org │ │ └── tatools │ │ └── sunshine │ │ └── testng │ │ ├── LoadableTestNGSuiteTest.java │ │ ├── SunshineTestNGTest.java │ │ ├── TestNGKernelTest.java │ │ ├── TestNGStatusTest.java │ │ └── TestNGTestTest.java │ └── resources │ └── testng.xml └── workflows /.0pdd.yml: -------------------------------------------------------------------------------- 1 | errors: 2 | - dmytro.serdiuk@gmail.com 3 | 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Check out all text files in UNIX format, with LF as end of line 2 | # Don't change this file. If you have any ideas about it, please 3 | # submit a separate issue about it and we'll discuss. 4 | 5 | * text=auto eol=lf 6 | *.java ident 7 | *.xml ident 8 | *.png binary 9 | -------------------------------------------------------------------------------- /.github/workflows/quality-pipeline.yaml: -------------------------------------------------------------------------------- 1 | name: Quality pipeline 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | steps: 11 | - uses: actions/checkout@v1 12 | - name: Set up JDK 1.8 13 | uses: actions/setup-java@v1 14 | with: 15 | java-version: 1.8 16 | - name: Build with Gradle 17 | run: ./workflows testing 18 | - name: Upload coverage to Codecov 19 | uses: codecov/codecov-action@v1.0.3 20 | with: 21 | token: ${{secrets.CODECOV_TOKEN}} 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | .gradle/ 14 | .idea/ 15 | build/ 16 | .DS_Store 17 | _build/ 18 | .python-version 19 | *.iml 20 | out/ 21 | -------------------------------------------------------------------------------- /.rultor.yml: -------------------------------------------------------------------------------- 1 | architect: extsoft 2 | docker: 3 | image: yegor256/java8 4 | install: |- 5 | java -version 6 | export LC_ALL=en_US.UTF-8 7 | export LANG=en_US.UTF-8 8 | export LANGUAGE=en_US.UTF-8 9 | sudo gem install pdd 10 | merge: 11 | fast-forward: only 12 | rebase: true 13 | script: |- 14 | ./gradlew --info 15 | ./gradlew clean 16 | pdd --source=$(pwd) --verbose --file=/dev/null 17 | commanders: 18 | - extsoft 19 | - Mras 20 | decrypt: 21 | gradle.properties: "repo/scrt/gradle.properties.asc" 22 | secring.gpg: "repo/scrt/secring.gpg.asc" 23 | release: 24 | commanders: extsoft 25 | script: |- 26 | cp -v ../gradle.properties ../secring.gpg ./ 27 | ./gradlew updateVersion -PnewVersion=${tag} 28 | ./gradlew clean ready signMavenPublication bintrayUpload --info 29 | -------------------------------------------------------------------------------- /.workflows/amend-work-after: -------------------------------------------------------------------------------- 1 | save-work-after -------------------------------------------------------------------------------- /.workflows/amend-work-ahead: -------------------------------------------------------------------------------- 1 | save-work-ahead -------------------------------------------------------------------------------- /.workflows/save-work-after: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ./workflows testing 3 | -------------------------------------------------------------------------------- /.workflows/save-work-ahead: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | ./workflows formatting 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sunshine 2 | Sunshine allows you to manage suits of your automated tests directly from Java code. It supports 3 | [TestNg](https://testng.org/doc/index.html), [JUnit 4](https://junit.org/junit4/), and 4 | [JUnit 5](https://junit.org/junit5/). 5 | 6 | Please read the documentation at https://sunshine.readthedocs.io. 7 | 8 | [![Build Status](https://github.com/tatools/sunshine/workflows/Quality%20pipeline/badge.svg)](https://github.com/tatools/sunshine/actions?workflow=Quality+pipeline) 9 | [![Documentation Status](https://readthedocs.org/projects/sunshine/badge/?version=latest)](http://sunshine.tatools.org/en/latest/?badge=latest) 10 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/b9ccdf7644db4658bb998eb3c8f0689b)](https://www.codacy.com/app/extsoft/sunshine?utm_source=github.com&utm_medium=referral&utm_content=tatools/sunshine&utm_campaign=Badge_Grade) 11 | [![codebeat badge](https://codebeat.co/badges/74ffce5e-e3be-45b7-9459-98d13f5f4d4e)](https://codebeat.co/projects/github-com-tatools-sunshine-master) 12 | [![codecov](https://codecov.io/gh/tatools/sunshine/branch/master/graph/badge.svg)](https://codecov.io/gh/tatools/sunshine) 13 | [![PDD status](http://www.0pdd.com/svg?name=tatools/sunshine)](http://www.0pdd.com/p?name=tatools/sunshine) 14 | 15 | [![assistant: Elegant Git](https://img.shields.io/badge/assistant-Elegant%20Git-000000.svg)](https://github.com/bees-hive/elegant-git) 16 | 17 | [![Rultor.com](http://www.rultor.com/b/tatools/sunshine)](http://www.rultor.com/p/tatools/sunshine) 18 | 19 | ## How to contribute? 20 | If you have any questions or want more functionality, please submit [a new issue](https://github.com/tatools/sunshine/issues/new). 21 | 22 | Before sending any pull request, please discuss requirements/changes to be implemented using an existing issue or 23 | by creating a new one. 24 | 25 | ## Development notes 26 | If you will install and use Git via CLI, all required workflows 27 | will be executed automatically. Otherwise, you can do it manually by running `./workflows` script. 28 | 29 | ### Code formatting 30 | We use to format the code. Please run 31 | `./gradlew spotlessApply` to call the formatting manually. 32 | 33 | ### Code assessment 34 | Run `./gradlew` (or `gradlew.bat`). It will execute unit, integration tests, and formatting verifications. 35 | 36 | ### Docs review 37 | Automatic analysis of documentation changes in not configured. That's why manual validation is required. 38 | 39 | The following snippet allows generation of HTML version of the documentation 40 | ```bash 41 | cd docs 42 | rm -r _build && make html 43 | open _build/html/index.html 44 | ``` 45 | 46 | Please take into account, you need to install required Python's dependencies with `pip install -r docs/requirements.txt` 47 | before. 48 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.jfrog.bintray" version "1.8.4" apply false 3 | id "com.diffplug.gradle.spotless" version "3.25.0" 4 | } 5 | 6 | ext { 7 | GITHUB_URL = "https://github.com/tatools/sunshine" 8 | BINTRAY_ORG = "tatools" 9 | } 10 | repositories { 11 | mavenLocal() 12 | jcenter() 13 | mavenCentral() 14 | } 15 | 16 | spotless { 17 | apply plugin: 'java' 18 | format 'misc', { 19 | target '**/*.gradle', '**/*.md', '**/.gitignore' 20 | trimTrailingWhitespace() 21 | indentWithSpaces() 22 | endWithNewline() 23 | } 24 | java { 25 | removeUnusedImports() 26 | indentWithSpaces() 27 | trimTrailingWhitespace() 28 | endWithNewline() 29 | 30 | custom 'Lambda fix', { it.replace('} )', '})').replace('} ,', '},') } 31 | 32 | // use standard modifier order (JLS 4.8.7 Modifiers) 33 | // public protected private abstract static final transient volatile synchronized native strictfp 34 | replaceRegex 'Modifier order 1', '^(\\s*)((?:static)|(?:final)|(?:abstract))\\s+((public)|(protected)|(private))\\s', '$1$3 $2 ' 35 | replaceRegex 'Modifier order 2', '^(\\s*)final\\s+static\\s+((public)|(protected)|(private))\\s', '$1$2 static final ' 36 | replaceRegex 'Modifier order 3', '^(\\s*)static\\s+final\\s+((public)|(protected)|(private))\\s', '$1$2 static final ' 37 | replaceRegex 'Modifier order 4', '^(\\s*((public)|(protected)|(private))?\\s*)\\sfinal\\s+static', '$1 static final' 38 | 39 | // remove empty lines before end of block (closing "}") 40 | replaceRegex 'Remove empty lines before end of block', '\\n[\\n]+(\\s*})(?=\\n)', '\n$1' 41 | 42 | } 43 | freshmark { 44 | target '**/*.md' 45 | } 46 | } 47 | 48 | subprojects { 49 | apply plugin: 'java' 50 | group 'org.tatools' 51 | version "${version}" 52 | sourceCompatibility = JavaVersion.VERSION_1_8 53 | 54 | repositories { 55 | mavenLocal() 56 | jcenter() 57 | mavenCentral() 58 | } 59 | } 60 | project(':sunshine-core') { 61 | apply from: rootProject.file('gradle/jacoco.gradle') 62 | apply from: rootProject.file('gradle/bintray.gradle') 63 | dependencies { 64 | compileOnly project(':sunshine-core-deps') 65 | } 66 | } 67 | 68 | project(':sunshine-junit4') { 69 | apply from: rootProject.file('gradle/jacoco.gradle') 70 | apply from: rootProject.file('gradle/bintray.gradle') 71 | dependencies { 72 | compile project(':sunshine-core') 73 | } 74 | } 75 | 76 | project(':sunshine-junit4-integration-tests') { 77 | dependencies { 78 | compile project(':sunshine-junit4') 79 | } 80 | } 81 | 82 | project(':sunshine-testng') { 83 | apply from: rootProject.file('gradle/jacoco.gradle') 84 | apply from: rootProject.file('gradle/bintray.gradle') 85 | dependencies { 86 | compile project(':sunshine-core') 87 | } 88 | } 89 | 90 | project(':sunshine-testng-integration-tests') { 91 | dependencies { 92 | compile project(':sunshine-testng') 93 | } 94 | } 95 | 96 | project(':sunshine-junit5') { 97 | apply from: rootProject.file('gradle/jacoco.gradle') 98 | apply from: rootProject.file('gradle/bintray.gradle') 99 | dependencies { 100 | compile project(':sunshine-core') 101 | } 102 | } 103 | 104 | project(':sunshine-junit5-integration-tests') { 105 | dependencies { 106 | compile project(':sunshine-junit5') 107 | } 108 | } 109 | 110 | defaultTasks 'clean', 'ready' 111 | 112 | //task to write the version parameter given via command line into the "gradle.properties" files. 113 | // Call with: gradle updateVersion -PnewVersion=1.0.1-SNAPSHOT 114 | task('updateVersion') { 115 | if (project.hasProperty('newVersion')) { 116 | //set version in gradle settings 117 | project.version = project.newVersion 118 | project.subprojects?.each { it.version = project.version } 119 | 120 | //set version in all the gradle.properties files 121 | def file = new File('gradle.properties') 122 | if (file.getText().contains('version')) { 123 | new File(".").traverse(type: FileType.FILES, nameFilter: 'gradle.properties') { 124 | project.ant.replaceregexp(file: it, byline: true) { 125 | key = 'version' 126 | version = project.version 127 | regexp(pattern: "^(\\s*)$key((\\s*[=|:]\\s*)|(\\s+)).+\$") 128 | substitution(expression: "\\1$key\\2$version") 129 | } 130 | } 131 | } else { 132 | file.append('\nversion=' + project.version + '\n') 133 | } 134 | println 'Successfully changed project version in gradle.properties to \'' + project.version + '\'' 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SOURCEDIR = . 8 | BUILDDIR = _build 9 | 10 | # Put it first so that "make" without argument is like "make help". 11 | help: 12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 13 | 14 | .PHONY: help Makefile 15 | 16 | # Catch-all target: route all unknown targets to Sphinx using the new 17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 18 | %: Makefile 19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/master/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | # import os 16 | # import sys 17 | # sys.path.insert(0, os.path.abspath('.')) 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = 'Sunshine' 23 | copyright = '2018, Dmytro Serdiuk' 24 | author = 'Dmytro Serdiuk' 25 | 26 | # The short X.Y version 27 | version = '' 28 | # The full version, including alpha/beta/rc tags 29 | release = '' 30 | 31 | 32 | # -- General configuration --------------------------------------------------- 33 | 34 | # If your documentation needs a minimal Sphinx version, state it here. 35 | # 36 | # needs_sphinx = '1.0' 37 | 38 | # Add any Sphinx extension module names here, as strings. They can be 39 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 40 | # ones. 41 | extensions = [ 42 | 'sphinx.ext.imgmath', 43 | 'sphinx.ext.githubpages', 44 | 'sphinx.ext.autosectionlabel', 45 | 'recommonmark', 46 | 'sphinx_markdown_tables', 47 | ] 48 | 49 | # Add any paths that contain templates here, relative to this directory. 50 | templates_path = ['_templates'] 51 | 52 | # The suffix(es) of source filenames. 53 | # You can specify multiple suffix as a list of string: 54 | source_suffix = ['.rst', '.md'] 55 | 56 | # The master toctree document. 57 | master_doc = 'index' 58 | 59 | # The language for content autogenerated by Sphinx. Refer to documentation 60 | # for a list of supported languages. 61 | # 62 | # This is also used if you do content translation via gettext catalogs. 63 | # Usually you set "language" from the command line for these cases. 64 | language = None 65 | 66 | # List of patterns, relative to source directory, that match files and 67 | # directories to ignore when looking for source files. 68 | # This pattern also affects html_static_path and html_extra_path. 69 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 70 | 71 | # The name of the Pygments (syntax highlighting) style to use. 72 | pygments_style = None 73 | 74 | 75 | # -- Options for HTML output ------------------------------------------------- 76 | 77 | # The theme to use for HTML and HTML Help pages. See the documentation for 78 | # a list of builtin themes. 79 | # 80 | html_theme = 'alabaster' 81 | 82 | # Theme options are theme-specific and customize the look and feel of a theme 83 | # further. For a list of options available for each theme, see the 84 | # documentation. 85 | # 86 | # html_theme_options = {} 87 | 88 | # Add any paths that contain custom static files (such as style sheets) here, 89 | # relative to this directory. They are copied after the builtin static files, 90 | # so a file named "default.css" will overwrite the builtin "default.css". 91 | html_static_path = ['_static'] 92 | 93 | # Custom sidebar templates, must be a dictionary that maps document names 94 | # to template names. 95 | # 96 | # The default sidebars (for documents that don't match any pattern) are 97 | # defined by theme itself. Builtin themes are using these templates by 98 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', 99 | # 'searchbox.html']``. 100 | # 101 | # html_sidebars = {} 102 | 103 | 104 | # -- Options for HTMLHelp output --------------------------------------------- 105 | 106 | # Output file base name for HTML help builder. 107 | htmlhelp_basename = 'Sunshinedoc' 108 | 109 | 110 | # -- Options for LaTeX output ------------------------------------------------ 111 | 112 | latex_elements = { 113 | # The paper size ('letterpaper' or 'a4paper'). 114 | # 115 | # 'papersize': 'letterpaper', 116 | 117 | # The font size ('10pt', '11pt' or '12pt'). 118 | # 119 | # 'pointsize': '10pt', 120 | 121 | # Additional stuff for the LaTeX preamble. 122 | # 123 | # 'preamble': '', 124 | 125 | # Latex figure (float) alignment 126 | # 127 | # 'figure_align': 'htbp', 128 | } 129 | 130 | # Grouping the document tree into LaTeX files. List of tuples 131 | # (source start file, target name, title, 132 | # author, documentclass [howto, manual, or own class]). 133 | latex_documents = [ 134 | (master_doc, 'Sunshine.tex', 'Sunshine Documentation', 135 | 'Dmytro Serdiuk', 'manual'), 136 | ] 137 | 138 | 139 | # -- Options for manual page output ------------------------------------------ 140 | 141 | # One entry per manual page. List of tuples 142 | # (source start file, name, description, authors, manual section). 143 | man_pages = [ 144 | (master_doc, 'sunshine', 'Sunshine Documentation', 145 | [author], 1) 146 | ] 147 | 148 | 149 | # -- Options for Texinfo output ---------------------------------------------- 150 | 151 | # Grouping the document tree into Texinfo files. List of tuples 152 | # (source start file, target name, title, author, 153 | # dir menu entry, description, category) 154 | texinfo_documents = [ 155 | (master_doc, 'Sunshine', 'Sunshine Documentation', 156 | author, 'Sunshine', 'One line description of project.', 157 | 'Miscellaneous'), 158 | ] 159 | 160 | 161 | # -- Options for Epub output ------------------------------------------------- 162 | 163 | # Bibliographic Dublin Core info. 164 | epub_title = project 165 | 166 | # The unique identifier of the text. This can be a ISBN number 167 | # or the project homepage. 168 | # 169 | # epub_identifier = '' 170 | 171 | # A unique identification for the text. 172 | # 173 | # epub_uid = '' 174 | 175 | # A list of files that should not be packed into the epub file. 176 | epub_exclude_files = ['search.html'] 177 | 178 | 179 | # -- Extension configuration ------------------------------------------------- -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. Sunshine documentation master file, created by 2 | sphinx-quickstart on Sat Nov 24 15:08:53 2018. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to Sunshine's documentation! 7 | ==================================== 8 | .. _TestNG: https://testng.org/doc/index.html 9 | .. _JUnit4: https://junit.org/junit4/ 10 | .. _JUnit5: https://junit.org/junit5/ 11 | 12 | 13 | Sunshine allows you to manage suits of your automated tests directly from Java code. It supports 14 | TestNG_, JUnit4_, and JUnit5_. 15 | 16 | .. toctree:: 17 | :maxdepth: 3 18 | 19 | md/concept.md 20 | md/getting-started.md 21 | md/artifacts.md 22 | md/entry-points.md 23 | 24 | .. note:: 25 | Please read the :ref:`Concept` to understand how it works before moving to :ref:`Getting started`. 26 | 27 | .. _GitHub repository: https://github.com/tatools/sunshine 28 | 29 | Want to contribute? Please visit `GitHub repository`_. 30 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/md/artifacts.md: -------------------------------------------------------------------------------- 1 | # Artifacts 2 | 3 | Sunshine consists of 4 libraries 4 | - `sunshine-core` provides interfaces and common implementations 5 | - `sunshine-junit4` wraps JUnit 4 to allow the creation of [entry points](entry-points.md) 6 | - `sunshine-junit5` wraps JUnit 5 to allow the creation of [entry points](entry-points.md) 7 | - `sunshine-testng` wraps TestNG to allow the creation of [entry points](entry-points.md) 8 | 9 | Since `0.4.x` version Sunshine uses `org.tatools` group ID. If you need the earlier version 10 | please use `io.github.tatools` instead. 11 | 12 | ## `sunshine-core` 13 | Artifacts: 14 | [![](https://img.shields.io/maven-central/v/org.tatools/sunshine-core.svg)](https://search.maven.org/search?q=g:%22org.tatools%22%20AND%20a:%22sunshine-core%22) 15 | [![](https://www.javadoc.io/badge/org.tatools/sunshine-core.svg)](https://www.javadoc.io/doc/org.tatools/sunshine-core) 16 | 17 | ## `sunshine-junit4` 18 | The library is tested on JUnit 4 `4.11`. 19 | 20 | Artifacts: 21 | [![](https://img.shields.io/maven-central/v/org.tatools/sunshine-junit4.svg)](https://search.maven.org/search?q=g:%22org.tatools%22%20AND%20a:%22sunshine-junit4%22) 22 | [![](https://www.javadoc.io/badge/org.tatools/sunshine-junit4.svg)](https://www.javadoc.io/doc/org.tatools/sunshine-junit4) 23 | 24 | ## `sunshine-junit5` 25 | The library is tested on Jupiter `5.5.2` and Platform `1.5.2`. 26 | 27 | Artifacts: 28 | [![](https://img.shields.io/maven-central/v/org.tatools/sunshine-junit5.svg)](https://search.maven.org/search?q=g:%22org.tatools%22%20AND%20a:%22sunshine-junit5%22) 29 | [![](https://www.javadoc.io/badge/org.tatools/sunshine-junit5.svg)](https://www.javadoc.io/doc/org.tatools/sunshine-junit5) 30 | 31 | ## `sunshine-testng` 32 | The library is tested on TestNG `6.11`. 33 | 34 | Artifacts: 35 | [![](https://img.shields.io/maven-central/v/org.tatools/sunshine-testng.svg)](https://search.maven.org/search?q=g:%22org.tatools%22%20AND%20a:%22sunshine-testng%22) 36 | [![](https://www.javadoc.io/badge/org.tatools/sunshine-testng.svg)](https://www.javadoc.io/doc/org.tatools/sunshine-testng) 37 | -------------------------------------------------------------------------------- /docs/md/concept.md: -------------------------------------------------------------------------------- 1 | # Concept 2 | 3 | Modern build tools such as [Maven](https://maven.apache.org) or [Gradle](https://gradle.org) have 4 | a test phase of the build lifecycle to execute the unit tests of an application. This capability is 5 | used in the automated testing to manage the execution of automated tests (instead of unit tests). 6 | As the result, all automated tests are located under `src/test` as well as any test execution 7 | configurations are managed through the build tools. 8 | 9 | The used solution has 3 main gaps: 10 | 1. **There is no place for unit tests as it is already owned by automated tests.** But sometimes 11 | unit tests are useful even for the automated testing as they allow to check some specific 12 | implementations to be used during the automation. 13 | 2. **Hard to configure tests suites.** This is because you need to run all unit tests at the same 14 | time during the project’s build cycle. And build tools support it very well. But for automated 15 | tests, it is often required to run only a subset of tests (or even only single test). The build 16 | tools are not so good at doing this. 17 | 3. **There is no chance to create a JAR file and distribute automated tests like a standard 18 | Java archive.** That's why in addition to a Java installation, build tool and other dependencies are 19 | required to run the tests. And this is a pain especially if you are supporting the tests execution 20 | or trying to dockerize them. 21 | 22 | **What does Sunshine offer?** 23 | 24 | It wraps a test runner and allows programmatic configuration of the tests suites. This decouples 25 | automated tests execution from a build tool and moves a project with automated tests toward 26 | [the regular Java project structure](https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html). 27 | 28 | Want to see a small demonstration? Please check out the video 29 | 30 | 31 | The code is located on [https://github.com/extsoft/jcat](https://github.com/extsoft/jcat). Feel free to check it out 32 | and make your own experiments. 33 | 34 | Now you are ready to move further with [Getting started](getting-started.md). 35 | -------------------------------------------------------------------------------- /docs/md/entry-points.md: -------------------------------------------------------------------------------- 1 | # Entry points 2 | An entry point is a Java class which is configured for a JAR and will be used when 3 | ```bash 4 | java -jar my.jar 5 | ``` 6 | is executed. 7 | 8 | ## Design custom entry point 9 | The `org.tatools.sunshine.core` package provides 3 main interfaces which are a base for any 10 | Sunshine's wrapper: 11 | - `Suite` defines a test suite and may be adapted to a test runner 12 | - `Kernel` runs encapsulated `Suite` on desired test runner 13 | - `Star` reports `Kernel`'s execution status to command line interface 14 | 15 | Also, there is a `SunshineSuite` interface with several core implementations which allow seeking 16 | and filtering of the classes to be treated as tests. Sunshine uses a string representation of a class 17 | as an input to a filter which uses 18 | [Java pattern matching](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html) 19 | to filter classes. For instance, there is a `LoginTest` class in `com.example.mypackage` package. 20 | It will be converted to `com.example.mypackage.LoginTest` and then put to a filter. 21 | 22 | Each wrapper provides its own implementations at least for `Suite` and `Kernel`. For instance, 23 | if the classes located in `pro.extsoft.comments.tests` package have to be executed by TestNG and 24 | status of the execution has to be reported to the CLI, the code snippet will look like 25 | ```java 26 | new Sun( 27 | new TestNGKernel( 28 | new LoadableTestNGSuite( 29 | new RegexCondition("^pro.extsoft.comments.tests(.+)?") 30 | ) 31 | ) 32 | ).shine(); 33 | ``` 34 | You can wrap it with any additional logic which is required for your tests execution. For instance, 35 | some input arguments can be read to generate test data before testing, etc. 36 | 37 | If you need an example, please take a look for [jcat repository](https://github.com/extsoft/jcat/blob/master/src/main/java/pro/extsoft/comments/App.java). 38 | 39 | ## Default TestNG entry point 40 | Class: [`org.tatools.sunshine.testng.Sunshine`](https://github.com/tatools/sunshine/blob/master/sunshine-testng/src/main/java/org/tatools/sunshine/testng/Sunshine.java) 41 | 42 | The class exposes the following behavior: 43 | 1. `java -jar my.jar` seeks for classes with word `Test` in the class name (a filter uses 44 | `(.+)(Test)([\w\d]+)?` regex), runs discovered tests, and reports results to the CLI. 45 | 2. `java -Dtests-regex="^(com.company.smoke)(.+)" -jar my.jar` does the same as the previous one except 46 | a class name has to match with `^(com.company.smoke)(.+)` regex. 47 | 3. `java -jar my.jar testng.xml` runs tests defined in `testng.xml` file (it can be either 48 | [TestNG XML](http://testng.org/doc/documentation-main.html#testng-xml) or 49 | [TestNG YAML](http://testng.org/doc/documentation-main.html#yaml)). 50 | 51 | 52 | ## Default JUnit 4 entry point 53 | Class: [`org.tatools.sunshine.junit4.Sunshine`](https://github.com/tatools/sunshine/blob/master/sunshine-junit4/src/main/java/org/tatools/sunshine/junit4/Sunshine.java) 54 | 55 | The class exposes the same behavior as default TestNG entry point exposes except the last option. All tests will be 56 | executed using JUnit 4. 57 | 58 | ## Default JUnit 5 entry point 59 | Class: [`org.tatools.sunshine.junit5.Sunshine`](https://github.com/tatools/sunshine/blob/master/sunshine-junit5/src/main/java/org/tatools/sunshine/junit5/Sunshine.java) 60 | 61 | The class exposes the same behavior as default TestNG entry point exposes except the last option. All tests will be 62 | executed using JUnit 5. 63 | 64 | ## Code snippets for different use cases 65 | ### Specify regex 66 | There is a regex which has used to filter classes from current classpath. 67 | 68 | TestNG sample 69 | ```java 70 | new Sun( 71 | new TestNGKernel( 72 | new LoadableTestNGSuite( 73 | new VerboseRegex( 74 | new RegexCondition("^my.package(.+)?") 75 | ) 76 | ) 77 | ) 78 | ).shine(); 79 | ``` 80 | JUnit 4 sample 81 | ```java 82 | new Sun( 83 | new Junit4Kernel( 84 | new JunitSuite( 85 | new VerboseRegex( 86 | new RegexCondition("^my.package(.+)?") 87 | ) 88 | ) 89 | ) 90 | ).shine(); 91 | ``` 92 | 93 | ### Specify classes directly 94 | There are some classes which have to be treat as a test suite. 95 | 96 | TestNG sample 97 | ```java 98 | new Sun( 99 | new TestNGKernel( 100 | new LoadableTestNGSuite( 101 | new SuiteFromClasses( 102 | TestNGTest1.class, 103 | TestNGTest2.class, 104 | TestNGTest3.class 105 | ) 106 | ) 107 | ) 108 | ).shine(); 109 | ``` 110 | JUnit 4 sample 111 | ```java 112 | new Sun( 113 | new Junit4Kernel( 114 | new JunitSuite( 115 | new SuiteFromClasses( 116 | JUnitTest1.class, 117 | JUnitTest2.class, 118 | JUnitTest3.class 119 | ) 120 | ) 121 | ) 122 | ).shine(); 123 | ``` 124 | 125 | ### Sequential execution of `Kernel`s 126 | There is a suite of tests which needs to be checked with several different listeners. For instance, 127 | if a listener is not configured, the tests will use some cache, otherwise, no cache before each test. 128 | And we have to run the suite with and without the listener. 129 | 130 | There is a specific `Kernel` called `SequentialExecution` which allows execution of described use case: 131 | ```java 132 | final Kernel suite = new TestNGKernel(....); 133 | new Sun( 134 | new SequentialExecution<>( 135 | suite, 136 | suite.with(new CleanCacheListener()) 137 | ) 138 | ).shine(); 139 | ``` 140 | -------------------------------------------------------------------------------- /docs/md/getting-started.md: -------------------------------------------------------------------------------- 1 | # Getting started 2 | You need to follow several steps to integrate Sunshine with your automated tests. 3 | 4 | ## Step 1: Make proper project's structure 5 | Suppose, there is a Maven project with automated tests 6 | ``` 7 | . 8 | ├── README.md 9 | ├── pom.xml 10 | └── src 11 |    ├── main 12 |    └── test 13 | ``` 14 | Usually, the code is located under `src/main` directory and automated tests under `src/test`. 15 | According to [Sunshine's concept](concept.md), the code and automated tests have to live together in `src/main`. 16 | 17 | So, please move everything to `src/main` except unit tests. 18 | 19 | ## Step 2: Add Sunshine library 20 | Based on the xUnit engine you are using, please select an appropriate library and add to your build configuration. 21 | Available libraries: 22 | - [![](https://img.shields.io/maven-central/v/org.tatools/sunshine-testng.svg?label=sunshine-testng)](https://search.maven.org/search?q=g:%22org.tatools%22%20AND%20a:%22sunshine-testng%22) 23 | - [![](https://img.shields.io/maven-central/v/org.tatools/sunshine-junit4.svg?label=sunshine-junit4)](https://search.maven.org/search?q=g:%22org.tatools%22%20AND%20a:%22sunshine-junit4%22) 24 | - [![](https://img.shields.io/maven-central/v/org.tatools/sunshine-junit5.svg?label=sunshine-junit5)](https://search.maven.org/search?q=g:%22org.tatools%22%20AND%20a:%22sunshine-junit5%22) 25 | 26 | To find out more references, please visit [artifacts page](artifacts.md). 27 | 28 | ## Step 3: Configure code packaging 29 | The recommended packaging is an `uber-JAR` - also known as a `fat JAR` or `JAR with dependencies` - 30 | is a JAR file that contains not only a Java program but embeds its dependencies as well. 31 | 32 | How to configure an uber-JAR depends on a build tool is used by a project. But regardless of a way 33 | of the configuration, [a JAR's entry point](https://docs.oracle.com/javase/tutorial/deployment/jar/appman.html) 34 | has to be defined. 35 | 36 | There are predefined classes to be used as the entry points for each test runner. However, 37 | Sunshine was designed to encourage you to create your own configurations based on the project's requirements. 38 | Please visit [entry points page](entry-points.md) to find out more. 39 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx==1.8.2 2 | # recommonmark==0.5.0.dev0 3 | git+https://github.com/rtfd/recommonmark 4 | sphinx-markdown-tables==0.0.9 5 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | signing.keyId= 2 | signing.password= 3 | signing.secretKeyRingFile= 4 | # sonatype 5 | sonatypeUsername= 6 | sonatypePassword= 7 | # bintray 8 | bintrayUser= 9 | bintrayApiKey= 10 | -------------------------------------------------------------------------------- /gradle/bintray.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.jfrog.bintray' 2 | apply plugin: 'maven' 3 | apply plugin: 'maven-publish' 4 | apply plugin: 'signing' 5 | 6 | task javadocJar(type: Jar) { 7 | classifier = 'javadoc' 8 | from javadoc 9 | } 10 | 11 | task sourcesJar(type: Jar) { 12 | classifier = 'sources' 13 | from sourceSets.main.allSource 14 | } 15 | 16 | artifacts { 17 | archives jar 18 | archives javadocJar 19 | archives sourcesJar 20 | } 21 | 22 | // Create the pom configuration: 23 | def pomConfig = { 24 | licenses { 25 | license { 26 | name "The Apache Software License, Version 2.0" 27 | url "http://www.apache.org/licenses/LICENSE-2.0.txt" 28 | distribution "repo" 29 | } 30 | } 31 | developers { 32 | developer { 33 | id 'extsoft' 34 | name 'Dmytro Serdiuk' 35 | email 'dmytro.serdiuk@gmail.com' 36 | } 37 | } 38 | 39 | scm { 40 | url GITHUB_URL 41 | } 42 | } 43 | 44 | // Create the publication with the pom configuration: 45 | publishing { 46 | publications { 47 | maven(MavenPublication) { 48 | from components.java 49 | artifact sourcesJar 50 | artifact javadocJar 51 | groupId project.group 52 | artifactId project.name 53 | version project.version 54 | pom.withXml { 55 | def root = asNode() 56 | root.appendNode('description', DESCRIPTION) 57 | root.appendNode('name', NAME) 58 | root.appendNode('url', GITHUB_URL) 59 | root.children().last() + pomConfig 60 | } 61 | } 62 | } 63 | } 64 | 65 | signing { 66 | sign publishing.publications.maven 67 | } 68 | 69 | bintray { 70 | user = bintrayUser 71 | key = bintrayApiKey 72 | publications = ['maven'] 73 | publish = true 74 | filesSpec { 75 | from("${buildDir}/libs") { 76 | include '*.jar.asc' 77 | } 78 | from("${buildDir}/publications/maven") { 79 | include 'pom-default.xml.asc' 80 | rename 'pom-default.xml.asc', "${project.name}-${project.version}.pom.asc" 81 | } 82 | into "${project.group.replaceAll(/\./, '/')}/${project.name}/${project.version}" 83 | } 84 | pkg { 85 | userOrg = BINTRAY_ORG 86 | repo = rootProject.name 87 | name = project.name 88 | licenses = ['Apache-2.0'] 89 | vcsUrl = GITHUB_URL 90 | publicDownloadNumbers = true 91 | version { 92 | name = project.version 93 | vcsTag = project.version 94 | mavenCentralSync { 95 | sync = true 96 | user = sonatypeUsername 97 | password = sonatypePassword 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /gradle/jacoco.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'jacoco' 2 | 3 | jacocoTestReport { 4 | reports { 5 | xml.enabled = true 6 | html.enabled = true 7 | } 8 | } 9 | check.dependsOn(jacocoTestReport) 10 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tatools/sunshine/e2bd652b47e1a1c8e6a78035e8caa56ab38710a3/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /scrt/gradle.properties.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP MESSAGE----- 2 | 3 | hQEMA5qETcGag5w6AQf+OSXDxIfEmgUjV8K2LvgFttq2uUs/DDvgzvU4UTtAAZen 4 | 1osFZg731uKJFbUl99feUA6EBL7v1N3mfj7QpPcSeCqIG9G19nJQ7NoQpG7/IZ5F 5 | WtFLWT9yPrsTwMR9SgBU4AK3uRZEIKMWyzMEN0+Xn0rZRvzd3G3cVpGuRnkNctcV 6 | iQOC4Whtt6KHdT+aelm1TJqYngAzb4RoNIM5Rdge2JfhCSMzz5ZTYUkx6vtnHj4k 7 | IeRlCrJkJgo/egXsBTeoEb/vA7KzZUhFV9NZbD/w0xznKIXE2peOlUwqiKRlQnAR 8 | OuFjhE06aDNjyymtx+OSOoJ+nkqBOMClFmUKoRHZbNLA7gG89Icp10ZKl/ds2YaI 9 | 6N8fr7I/tTZUO+tCiX9pn7rYvEno/icc/xmSNzun6UAlxJk30Lhyc0+Rs1iqDmnx 10 | JW8iwQTdxXACEJ+jk2t9XFZca1EuJmK0Lk4HXGCWSHeZfshV68BZrOrE0XikY4jo 11 | 4+cg6Uiymcm8/+kBfzBhlQw2XwnFcWbr13eZqCrYaeTQfeU495dszIh7CJNVHMRv 12 | UHj1Dixif1nfiDtdxUFCz/N4vV8kzSJ1fU9WZgiaJpXyakwqBAS/vKnwe5hn0IQ9 13 | t0Hkcagwoyzf7sV00YXGLgMZARpyZHfrKEuyBkuAqAJAtkfDvVlTdr5WK1+ofWqI 14 | gHZQbnJLBfmKaR23Hih45UZOqPtz3hhrwTh8wfRtnqeiHV3xugELDAWELtAe0Rjz 15 | dSelWhPdIuqBMPOCK5WS22ST/VCIYch4efI9tZHvpyjweNBi1jswBlJykiW/6GUo 16 | Iy4NtFIE3jE5YTtnA+CK/pc8iJHQpmHdc/H/1ROHBzchv9KXdgYUOCX0rMzkVspH 17 | w3Xiw+TQxzht/D6OF0eGwSAIwgeGKNScmHXjZaTovmo= 18 | =iG01 19 | -----END PGP MESSAGE----- 20 | -------------------------------------------------------------------------------- /scrt/secring.gpg.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP MESSAGE----- 2 | 3 | hQEMA5qETcGag5w6AQf9HD7dKuBASeK88UykS8KAXxGTx0CXjGzAHeqq2ciQAmF5 4 | JrzlxknrW5V6t//a3vWQ9gojJoDkROH4BHyWMH+JcCI709DAlE/GSl5xX+LF6KZf 5 | rrVaLRNEOaW0d6EoivDrbHX5wP8xaFnYbN4ZZBUSEmopqalflLi0e33K3doucB3m 6 | e88YSTHFGA7BE6WEDUIKHbagsSA2sb06Uno3KX5ShW6U/voFq5Pv4YT5zhO67PRd 7 | CA9k8FQftQxSSLhMvdo2JzyefWMXMUtkC5vmIQ1ZNFmtbt5BYoxZhh9HkW5KVNio 8 | Hckts659ztbwjpBXgAEf3UVg1t5IHNuYmVuoQpGOE9LrAXQpKFPhTNYlWcyQzdkw 9 | 25Y31mpQvnpGo9ZoK3/JCzE/cZc1LFh39C0ldFuS48gX5leyvjJ/dmFi1UIt1EcH 10 | yCk/29J8YMCfpghzFpGkhTWZVi6sWhVu+uaYfNdR5B/vlEdpivyeKD6LlIPwzY0v 11 | qLD9C+CncHyT8NOqfkkJVPcvkn8L3R5EkFkEj/laxPTDQ4Zlg9ECmz+3CsbDiq+x 12 | aVqBhDus00dLrgModDTcrd9/b1a7Qq7z1NXHpw15giRGRkddI6C9clqDyMOaATJI 13 | FnSZBw/Cq1ldrMe7UfZe7qPlV3lRUv7yKLlVfy1EL30Ob8tHOGC9YmVQH33+Nhxx 14 | vinagUlfLEqKRbw3n6JtrUA+jkXylzoCe6tveAlzRH4Eic/Ggl/BnYtKz05LSwjr 15 | VrlGyyZRGzM+KU5jeVQBnKEwx0naZovpUxVAiIADal+VZ7AfTaf5JX5mdzhofygm 16 | gqcPK5VSg7CAOWvXpyaCZUHtbQwjRiLDLtsh4H4261NZUqYODvjgI93P0gQlipAI 17 | mtF1sHhyOxMj1VxjECOuEwfBTjnQqX87+OIij779oswQ1i4XdHNoOpQCn2605ORU 18 | 2pgzmpg34g6FyhHtVc9YFqizbRk7Lz5ubyRE4XXmW2t4lscx+Mqli+qzYrGGtwmP 19 | jBsBOdzHgIYpV5TRnIXQIztF9vDS4YXDNQvTLOZSsWqsWhC29ADTj7BdGTTwMimW 20 | 0PnAW6XkkGczm0mrfppOKFKbnYxyYV9OmktLs9IMp7zMJUAbDDkDM8dGBhBDs/5F 21 | qH8wdFwdIqwbkcezOtfT/aSLjsIsVLIb5dP98RMZ/NPc0luuJg0l/bGp0Kd63rr1 22 | 4tqPjoduVHQx6Uob8uYFwDckP0fHBOuDr8HiNNaVV8CGmLBjnSyaj4bG29y8R/do 23 | pTw43rbDEtpPWDGXI3x2UK3LmCNZKh5lmnCiKfIMYqmD//geccFPHEiuF6ftDA9m 24 | FwwYACYt0Dc49BU2ZbYP3V4F9jcaXhw1Dh9VSD94Klv1Fktta9lup3HFV3xfOx4+ 25 | aBOusqDFLC4e0Rlhaw27GydCyruzFGlG784m14egOB87yLizlS3+/ve/xbe5+Usd 26 | 9LzxqAQsulTBchHqPdZPCb4fX05ouVKG5paZK7qXaPL9bVhgpIz5/cS8X6u2Ived 27 | AxRseGwWW+ckqecroBlfN80BgRyxi5M9TE7aTseEXX7yeMRmHrUP+n6B4G/nm8BP 28 | OH3e9KFgL//bEd8CQWvJI8xCLRIhVLFR+MynJeOvre9I12tG++plHpXTsyjSKiMy 29 | gpcBgiMT194BEBHEZOdF4Jtn9sHnTa7OY6izpkCiNUNoiRjQEuizXDGTXvnOibym 30 | are1h6PZ0OR75dtCZByMl0KRTIF0eco9cvtxCuU4L1B3vrPRlV53IsTP6gsuQ+02 31 | IWIC2pErAwVonKT+TvDaTtJA+Gi5RChlJ6KprasBZF7fNkIYlSaHyhgTb/jSYzDE 32 | d7kGuM5VjBylVXIs0Rmk62pXc8sL+YbYFk9lSBvy6ZAEUfCYbYZo8512tFM3F92r 33 | N7xyyEi6t9dX/75GlkwkgZSE37IG4P1nQ/6ARoIfaLDLfRgum9qAODEp1guDoNXI 34 | zPDWJ9YZE6qa2yne68NJ4xx2ghaPSkqrCgszsCGfBTtCjnZK80CkUvtmtOcP/ESH 35 | O6ne4sgIi4Apw8E3AO8XQ4CjtHa44dlyZ5aaFRgLkqj3WQ0yp/n4Jbf8u6iaFV31 36 | NXIjhGByEgMPL7avCZIUC1LHg+W91Pa8SE4KY90SBOirgSd+RUCcvjCGXsqpAwJf 37 | qua6ScZ5fgimhxVu3+tNuhn3jROzbF5d31f8NkkG4fnYLkcoB3L+OTX7LIs84sf5 38 | 8PAxKPPjHHraBsZwtlm/+NQBF9kcf7U1YqrO61D8LWe1S96LSq8k59n5lYhqCs2n 39 | zT+LOOSfWHuO5k552fM3CdqPXmrNpMAIv8K+vMU3xRdVoAQF7sfprQzkv1Nn8jjU 40 | CFYcv+8Rdszsb2mTiJgYnjub6G5oFzhOSnMKu91WWqXgrWcI680OcVxkneKiI2Il 41 | e0x/pJAKi4obC4C337hXfDxz/37rNlOqM6H+ECn/dhMO+Qn+/UhD/6M7wxAO9CVe 42 | S664n+lAfV2NOyjuqypUWaii+isqipJ9dMXdVeFw8TWdFM+8JW3nZ3wDwYYG1Qso 43 | j/lPdllVXkPOY+G6Z82OI6Z34YzdXoRPS/P2c7YXI8iDb/PkUkwJVlm8Qir4gPBj 44 | OIjgqERdSaJIb7gwLBeVeDPYUOH0SSg0j0q4FlCZtT9/P64ubq34B0Yk/oDUrT29 45 | v5n39rF5O1sf89SZS9fMXVbu+u2clPa6FzUWdZDcytkFarlw35Yv/8QM/00hapU7 46 | JQf/kaOrWPIeTUQKA0JysofP3jNo77NGeQnGIrqWkEDtNQogualWBNmlcDdNiggi 47 | nTnx3FIM3oeiWfLq2ETiUmULFJm4EoEgKRZUNhZ63ENohOBlcgSHUauiq6gX2A/5 48 | nd9nvEH1Rh+R77ucrZuroNLPjA3hB5VignggtfjI/1nCVAXvGHsyiDBn+YzpHfxq 49 | rkqVhsx3jZLoirx5xBPZd+S46BJMa7B/Mpu6S5lTYAKZ68XYuZb69hMjOvmZ1mjM 50 | nle+eCPAJr6PRuwnb1wr27Mg+COisaYINlmwg0OH535N2uAxlSM9xASO3l3S6blv 51 | co/JaWsGl7vB0mfvHllYgg7pIuaWHOzGIrwPdUgLMsQKBYiPXrETFqs4i+O7naLa 52 | NRRpxt5P3ARDp53oMLVKbUCY0yY9tSZpS+e1wMwBR3KxOTTFc4i9HOFTzauKVtNU 53 | wvIS4lAotwE/NlC3LDJRgI3SlemGUZ+JNApSp/SoE5aMnHlK04E88TA1hpxjDLqu 54 | fmuPMw24GmpQ65plrm8zDbwqRQrqnigoVwxjW6jmOXJU5XTdVpi6UAQerOz+2iRP 55 | H/1E2x6R6boAg6qlXGOisTrbpuA7cYtLDGSFgOmuQgPvCJvHprNVYwapoiqYP1Ka 56 | kDBYgDvLHyyJ0K1b161YidY7F3b+fVbdCyOZH0MvMMNmcvQifWvwfC/ljwNzM2Qr 57 | qZ13SzLAi2gCuYZcxPOMYWfesXzSi2enn2nubcranTP5WcJXVV+kPR9v+VhpGM68 58 | NefF2piFoMXXgiOOhwCFWVyUQYGolxzWJvb+nlvD17i3kUWZONGtQhPQryGw8UqG 59 | kL7zyAXorhiLCcRvALxniBFiINrJjGPCo8zXGNjFf5NvzGP8QNsk0cY8iO2/Q327 60 | wvp83vfxzr/uPjtG4dYzxdUK6efxZ7Q5TQouZ5xxWVWq9Q2zTN0lEMVdeqGxl8wZ 61 | 7vlesmFqqWhxAbgJV7HiZ50WxVvv7dQGKDP/9PnrXJO1l8ixilVg3nUvDpp/ADAq 62 | cLLAu6BfEsh03GGSH/n84VHj59uOgIQTbksTmIsFsjlWhS9G3DXmr/TVxWB7ob9W 63 | tKi7BIXfl7otprzAy/EBbmk6nJg/tEE0hVKA0uIcB2htedAT3Y+eD1mSYnyl9vpp 64 | 1ro8Wlt6q/6KogRRaJn1LwMt/PQDbEESZD/Qe45y4L+hgBKBoTFcQ0P6CeP3Hij1 65 | IsNTd0BKmTj8evZVQzMFqiz4maLEJzZpmxMXHDyTppkcjm182jpKiqLWz2Jggg5H 66 | RGrmXbuX0T463hKHS6KghPnbku56MUtERhubCPVYWGSN4ZAWmQv3i6ayptW6ogfn 67 | Qz3bHheC27ip+rBqNkDWnOLyeWbjpS1ijdWV+3ZS4RXgro3NkseWiy4nwJm50b++ 68 | 3rABDTyt66X9R7KUnnVi17T/2CgkaaBbvcxNECfoIfr9EHXfddBfoWWGy2sqEqzQ 69 | b+oedBrZgZoYdBphvz+8Tzajuas9l1G7gBxenqFQZ6CyS+37xxIzlnxsLh/z36A= 70 | =+V6l 71 | -----END PGP MESSAGE----- 72 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'sunshine' 2 | include 'sunshine-core-deps', 'sunshine-core' 3 | include 'sunshine-testng', 'sunshine-testng-integration-tests' 4 | include 'sunshine-junit4', 'sunshine-junit4-integration-tests' 5 | include 'sunshine-junit5', 'sunshine-junit5-integration-tests' 6 | -------------------------------------------------------------------------------- /sunshine-core-deps/build.gradle: -------------------------------------------------------------------------------- 1 | task ready(dependsOn: build) { 2 | doFirst { 3 | println("A JAR file for Sunshine unit testing is ready.") 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /sunshine-core-deps/src/main/java/org/tatools/testng/DisabledTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.testng; 2 | 3 | /** 4 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 5 | * @version $Id: b96858a92cae4b232d134ef67e021fe45ed78cdc $ 6 | * @since 0.1 7 | */ 8 | public class DisabledTest {} 9 | -------------------------------------------------------------------------------- /sunshine-core-deps/src/main/java/org/tatools/testng/FailedTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.testng; 2 | 3 | /** 4 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 5 | * @version $Id: 0069074d3b67a1689e65c3dda3d247afa003b97e $ 6 | * @since 0.1 7 | */ 8 | public class FailedTest {} 9 | -------------------------------------------------------------------------------- /sunshine-core-deps/src/main/java/org/tatools/testng/PassedTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.testng; 2 | 3 | /** 4 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 5 | * @version $Id: ac0eac08fc4f338cb3a8312cf0173e61937216a1 $ 6 | * @since 0.1 7 | */ 8 | public class PassedTest {} 9 | -------------------------------------------------------------------------------- /sunshine-core-deps/src/main/java/org/tatools/testng/SkippedTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.testng; 2 | 3 | /** 4 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 5 | * @version $Id: 62243cadffbb33b5d445ea795b243fac62757cfb $ 6 | * @since 0.1 7 | */ 8 | public class SkippedTest {} 9 | -------------------------------------------------------------------------------- /sunshine-core-deps/src/main/java/org/tatools/testng/Test1.java: -------------------------------------------------------------------------------- 1 | package org.tatools.testng; 2 | 3 | /** 4 | * This is an empty class. 5 | * 6 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 7 | * @version $Id: c7760ffdaba543e3b4728e3975f90043494dfe20 $ 8 | * @since 0.1 9 | */ 10 | public class Test1 {} 11 | -------------------------------------------------------------------------------- /sunshine-core-deps/src/main/java/org/tatools/testng/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The package is used to hold the classes for unit testing of the sunshine core. 3 | * 4 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 5 | * @version $Id: 541c9fd7ebfe54ec53134de146ee81488e79f455 $ 6 | * @since 0.2 7 | */ 8 | package org.tatools.testng; 9 | -------------------------------------------------------------------------------- /sunshine-core/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compileOnly 'org.projectlombok:lombok:1.16.14' 3 | annotationProcessor 'org.projectlombok:lombok:1.16.14' 4 | testCompile 'org.hamcrest:hamcrest-all:1.3' 5 | testCompile 'junit:junit:4.11' 6 | testCompile 'com.github.stefanbirkner:system-rules:1.18.0' 7 | } 8 | 9 | task copyUnitTestsDependencies(type: Copy) { 10 | from "../sunshine-core-deps/build/libs/sunshine-core-deps-${version}.jar" 11 | into "build" 12 | rename { 13 | "sample-tests.jar" 14 | } 15 | } 16 | 17 | test.dependsOn(copyUnitTestsDependencies) 18 | 19 | task ready(dependsOn: check) { 20 | doLast { 21 | println("Unit testing of Sunshine core is completed.") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sunshine-core/gradle.properties: -------------------------------------------------------------------------------- 1 | NAME="A core of Sunshine" 2 | DESCRIPTION="The package is a core API and partial implementation for the test runners' adapters." 3 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/CompositeStatus.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * The class represents several {@link Status}es as a single instance. 7 | * 8 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 9 | * @version $Id: d8a3a93c475a98563654d412d4446ff9b136f8dd $ 10 | */ 11 | public class CompositeStatus implements Status { 12 | 13 | private final List sources; 14 | 15 | /** 16 | * Constructs a new instance. 17 | * 18 | * @param statuses available statuses 19 | */ 20 | public CompositeStatus(List statuses) { 21 | this.sources = statuses; 22 | } 23 | 24 | /** 25 | * Returns the exit code of an execution provided by xunit tests runner. 26 | * 27 | *

The code will be a maximum value from all available codes expect zero ones. If there is no 28 | * maximal value, 0 is given (means all are passed), otherwise, a non-zero number (if there is 29 | * at least one failure). 30 | * 31 | * @return a calculated exit code 32 | */ 33 | @Override 34 | public final short code() { 35 | return this.sources.stream() 36 | .map(Status::code) 37 | .filter(code -> code != 0) 38 | .max(Short::compareTo) 39 | .orElse((short) 0); 40 | } 41 | 42 | /** 43 | * Returns a sum of all tests of all statuses. 44 | * 45 | * @return a count of total tests 46 | */ 47 | @Override 48 | public final int runCount() { 49 | return this.sources.stream().mapToInt(Status::runCount).sum(); 50 | } 51 | 52 | /** 53 | * Returns a sum of failed tests of all statuses. 54 | * 55 | * @return a count of failed tests 56 | */ 57 | @Override 58 | public final int failureCount() { 59 | return this.sources.stream().mapToInt(Status::failureCount).sum(); 60 | } 61 | 62 | /** 63 | * Returns a sum of ignored tests of all statuses. 64 | * 65 | * @return a count of ignored tests 66 | */ 67 | @Override 68 | public final int ignoreCount() { 69 | return this.sources.stream().mapToInt(Status::ignoreCount).sum(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/Condition.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | /** 4 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 5 | * @version $Id: cb9bb267860bcf751a878cfc55f58a7910a67070 $ 6 | * @since 0.1 7 | */ 8 | @FunctionalInterface 9 | public interface Condition { 10 | /** 11 | * Allows verifying this condition on an identity. The identity is the full name of a class like 12 | * "io.github.my.FirstTest". 13 | * 14 | * @param identity a full name of a class 15 | * @return true if the rule passes otherwise false 16 | */ 17 | boolean applicable(String identity); 18 | 19 | class Fake implements Condition { 20 | private final boolean answer; 21 | 22 | public Fake(boolean answer) { 23 | this.answer = answer; 24 | } 25 | 26 | @Override 27 | public boolean applicable(String identity) { 28 | return answer; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/Directory.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Path; 5 | 6 | /** 7 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 8 | * @version $Id: a09f635d888c5161f5baacbd74134393c2ed0b3a $ 9 | * @since 0.1 10 | */ 11 | public interface Directory extends FileSystemPath { 12 | void create() throws IOException; 13 | 14 | void remove() throws IOException; 15 | 16 | final class Fake implements Directory { 17 | private final Path path; 18 | private final boolean exist; 19 | 20 | public Fake(Path path) { 21 | this(path, false); 22 | } 23 | 24 | public Fake(Path path, boolean exist) { 25 | this.path = path; 26 | this.exist = exist; 27 | } 28 | 29 | @Override 30 | public void create() {} 31 | 32 | @Override 33 | public void remove() {} 34 | 35 | @Override 36 | public Path path() { 37 | return path; 38 | } 39 | 40 | @Override 41 | public boolean exist() { 42 | return exist; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/DirectoryBase.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.FileVisitOption; 5 | import java.nio.file.Files; 6 | import java.nio.file.Path; 7 | import java.util.Comparator; 8 | import lombok.EqualsAndHashCode; 9 | 10 | /** 11 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 12 | * @version $Id: 8b1a8cf5cbf3d6b8e007eda7707bd335e754550d $ 13 | * @since 0.1 14 | */ 15 | @EqualsAndHashCode 16 | public class DirectoryBase implements Directory { 17 | 18 | private final FileSystemPath fileSystemPath; 19 | 20 | public DirectoryBase(String path) { 21 | this(new FileSystemPathBase(path)); 22 | } 23 | 24 | public DirectoryBase(Path path) { 25 | this.fileSystemPath = new FileSystemPathBase(path); 26 | } 27 | 28 | public DirectoryBase(FileSystemPath fileSystemPath) { 29 | this.fileSystemPath = fileSystemPath; 30 | } 31 | 32 | @Override 33 | public final void create() throws IOException { 34 | Files.createDirectory(fileSystemPath.path()); 35 | } 36 | 37 | @Override 38 | public final void remove() throws IOException { 39 | Files.walk(fileSystemPath.path(), FileVisitOption.FOLLOW_LINKS) 40 | .sorted(Comparator.reverseOrder()) 41 | .map(Path::toFile) 42 | .forEach(java.io.File::delete); 43 | } 44 | 45 | @Override 46 | public final boolean exist() { 47 | return fileSystemPath.exist(); 48 | } 49 | 50 | @Override 51 | public final Path path() { 52 | return fileSystemPath.path(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/DirectorySafe.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Path; 5 | import lombok.EqualsAndHashCode; 6 | 7 | /** 8 | * The class allows communicating with a {@link Directory} object safely. This means it does not 9 | * touch real file system until it's really needed. 10 | * 11 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 12 | * @version $Id: c78cf1094433ddfad47f3603ab48e7b3cfdd255e $ 13 | * @since 0.1 14 | */ 15 | @EqualsAndHashCode 16 | public class DirectorySafe implements Directory { 17 | 18 | private final Directory directory; 19 | 20 | public DirectorySafe(String path) { 21 | this(new DirectoryBase(path)); 22 | } 23 | 24 | public DirectorySafe(Path path) { 25 | this(new DirectoryBase(path)); 26 | } 27 | 28 | public DirectorySafe(FileSystemPath path) { 29 | this(new DirectoryBase(path)); 30 | } 31 | 32 | public DirectorySafe(Directory directory) { 33 | this.directory = directory; 34 | } 35 | 36 | @Override 37 | public final void create() throws IOException { 38 | if (!directory.exist()) { 39 | directory.create(); 40 | } 41 | } 42 | 43 | @Override 44 | public final void remove() throws IOException { 45 | if (directory.exist()) { 46 | directory.remove(); 47 | } 48 | } 49 | 50 | @Override 51 | public final boolean exist() { 52 | return directory.exist(); 53 | } 54 | 55 | @Override 56 | public final Path path() { 57 | return directory.path(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/DirectoryWithAutomaticCreation.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Path; 5 | 6 | /** 7 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 8 | * @version $Id: 4c57730eba8fc5e85ea65c63cb809a4a961a7c12 $ 9 | * @since 0.1 10 | */ 11 | public class DirectoryWithAutomaticCreation implements Directory { 12 | 13 | private final Directory directory; 14 | 15 | public DirectoryWithAutomaticCreation(Directory directory) { 16 | this.directory = directory; 17 | } 18 | 19 | @Override 20 | public final void create() throws IOException { 21 | this.directory.create(); 22 | } 23 | 24 | @Override 25 | public final void remove() throws IOException { 26 | this.directory.remove(); 27 | } 28 | 29 | @Override 30 | public final Path path() { 31 | try { 32 | this.create(); 33 | return this.directory.path(); 34 | } catch (IOException e) { 35 | throw new RuntimeException(e); 36 | } 37 | } 38 | 39 | @Override 40 | public final boolean exist() { 41 | try { 42 | this.create(); 43 | return true; 44 | } catch (IOException e) { 45 | throw new RuntimeException(e); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/DirectoryWithAutomaticDeletion.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Path; 5 | 6 | /** 7 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 8 | * @version $Id: 696ffde08d24478a367ceefd70997f4811dd2909 $ 9 | * @since 0.1 10 | */ 11 | public class DirectoryWithAutomaticDeletion implements Directory { 12 | 13 | private final Directory directory; 14 | 15 | public DirectoryWithAutomaticDeletion(Directory directory) { 16 | this.directory = directory; 17 | } 18 | 19 | @Override 20 | public final void create() throws IOException { 21 | Runtime.getRuntime() 22 | .addShutdownHook( 23 | new Thread("ds") { 24 | @Override 25 | public void run() { 26 | try { 27 | directory.remove(); 28 | } catch (IOException e) { 29 | throw new RuntimeException(e); 30 | } 31 | } 32 | }); 33 | directory.create(); 34 | } 35 | 36 | @Override 37 | public final void remove() throws IOException { 38 | directory.remove(); 39 | } 40 | 41 | @Override 42 | public final Path path() { 43 | return directory.path(); 44 | } 45 | 46 | @Override 47 | public final boolean exist() { 48 | return directory.exist(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/File.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 7 | * @version $Id: 056d8d313d01106f52fed13326153385a98de047 $ 8 | * @since 0.1 9 | */ 10 | public interface File extends FileSystemPath { 11 | void write(String data) throws IOException; 12 | } 13 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/FileBase.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Files; 5 | import java.nio.file.Path; 6 | import lombok.EqualsAndHashCode; 7 | 8 | /** 9 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 10 | * @version $Id: df4008ff1c4d43bf6b5586b63958d1ed45133696 $ 11 | * @since 0.1 12 | */ 13 | @EqualsAndHashCode 14 | public class FileBase implements File { 15 | 16 | private final FileSystemPath fileSystemPath; 17 | 18 | public FileBase(Directory directory, String file) { 19 | this(new FileSystemPathBase(directory, file)); 20 | } 21 | 22 | public FileBase(String directory, String file) { 23 | this(new FileSystemPathBase(directory, file)); 24 | } 25 | 26 | public FileBase(Path directory, String file) { 27 | this(new FileSystemPathBase(directory, file)); 28 | } 29 | 30 | public FileBase(FileSystemPath fileSystemPath) { 31 | this.fileSystemPath = fileSystemPath; 32 | } 33 | 34 | @Override 35 | public final Path path() { 36 | return fileSystemPath.path(); 37 | } 38 | 39 | @Override 40 | public final boolean exist() { 41 | return fileSystemPath.exist(); 42 | } 43 | 44 | @Override 45 | public final void write(String data) throws IOException { 46 | Files.write(this.path(), data.getBytes()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/FileSystem.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | /** 7 | * The interface declares a place to search tests classes. 8 | * 9 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 10 | * @version $Id: 6b6d1b877bfd93f0b011fda337e27b25d04b9b8d $ 11 | * @since 0.1 12 | */ 13 | public interface FileSystem { 14 | /** 15 | * Returns a list of files within given file system. An implementation may support recursive 16 | * search or not. 17 | * 18 | * @return a list of files 19 | * @throws FileSystemException if some error occurs 20 | */ 21 | List files() throws FileSystemException; 22 | 23 | class Fake implements FileSystem { 24 | private final List files; 25 | 26 | public Fake(FileSystemPath... files) { 27 | this(Arrays.asList(files)); 28 | } 29 | 30 | Fake(List files) { 31 | this.files = files; 32 | } 33 | 34 | @Override 35 | public List files() { 36 | return files; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/FileSystemException.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | /** 4 | * The {@link FileSystemException} class is a default exception to handle errors which may occur in 5 | * the implementations of a {@link FileSystem} interface. 6 | * 7 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 8 | * @version $Id: d175a6bea8a1dbb777dea248481532be426a5720 $ 9 | * @since 0.1 10 | */ 11 | public class FileSystemException extends SunshineException { 12 | public FileSystemException(String message) { 13 | super(message); 14 | } 15 | 16 | public FileSystemException(String message, Throwable cause) { 17 | super(message, cause); 18 | } 19 | 20 | public FileSystemException(Throwable cause) { 21 | super(cause); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/FileSystemFiltered.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | import lombok.EqualsAndHashCode; 6 | 7 | /** 8 | * The {@link FileSystemFiltered} class allows to filter files by given condition. 9 | * 10 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 11 | * @version $Id: f14c4b16bf65b1433bf2d8e998c648bb4ff29d5a $ 12 | * @since 0.1 13 | */ 14 | @EqualsAndHashCode 15 | final class FileSystemFiltered implements FileSystem { 16 | 17 | private final FileSystem fileSystem; 18 | private final Condition condition; 19 | 20 | FileSystemFiltered(FileSystem fileSystem, Condition condition) { 21 | this.fileSystem = fileSystem; 22 | this.condition = condition; 23 | } 24 | 25 | @Override 26 | public List files() throws FileSystemException { 27 | return fileSystem.files().stream() 28 | .filter(f -> condition.applicable(f.path().toString())) 29 | .collect(Collectors.toList()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/FileSystemOfClasses.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.List; 4 | import lombok.EqualsAndHashCode; 5 | 6 | /** 7 | * The {@link FileSystemOfClasses} class allows to select only Java classes. 8 | * 9 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 10 | * @version $Id: 87a5e656ea8d6c4f4c71225c4c79b2aa450659bc $ 11 | * @since 0.1 12 | */ 13 | @EqualsAndHashCode 14 | final class FileSystemOfClasses implements FileSystem { 15 | 16 | private final FileSystem fileSystem; 17 | 18 | FileSystemOfClasses(FileSystem fileSystem) { 19 | this.fileSystem = 20 | new FileSystemFiltered( 21 | new FileSystemOfFileSystems( 22 | fileSystem, 23 | new FileSystemOfJarFiles( 24 | new FileSystemFiltered(fileSystem, new JarCondition()))), 25 | new ClassCondition()); 26 | } 27 | 28 | @Override 29 | public List files() throws FileSystemException { 30 | return fileSystem.files(); 31 | } 32 | 33 | private final class ClassCondition implements Condition { 34 | @Override 35 | public boolean applicable(String identity) { 36 | return identity.matches(".+\\.class$") && !identity.contains("$"); 37 | } 38 | } 39 | 40 | private final class JarCondition implements Condition { 41 | @Override 42 | public boolean applicable(String identity) { 43 | return identity.endsWith(".jar"); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/FileSystemOfClasspathClasses.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.File; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | import lombok.EqualsAndHashCode; 8 | 9 | /** 10 | * The {@link FileSystemOfClasspathClasses} class provides an implementation of {@link FileSystem} 11 | * interface which allows to find all Java classes in current Java CLASSPATH. 12 | * 13 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 14 | * @version $Id: 94e6206b0191344ba42cdfbc6d2895ae734975d3 $ 15 | * @since 0.1 16 | */ 17 | @EqualsAndHashCode 18 | public class FileSystemOfClasspathClasses implements FileSystem { 19 | 20 | private final FileSystem fileSystem; 21 | 22 | public FileSystemOfClasspathClasses() { 23 | this( 24 | new FileSystemOfClasses( 25 | new FileSystemOfFileSystems( 26 | Arrays.stream( 27 | System.getProperty("java.class.path") 28 | .split(File.pathSeparator)) 29 | .map(FileSystemOfPath::new) 30 | .collect(Collectors.toList())))); 31 | } 32 | 33 | private FileSystemOfClasspathClasses(FileSystem fileSystem) { 34 | this.fileSystem = fileSystem; 35 | } 36 | 37 | @Override 38 | public final List files() throws FileSystemException { 39 | return fileSystem.files(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/FileSystemOfFileSystems.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import lombok.EqualsAndHashCode; 6 | 7 | /** 8 | * The {@link FileSystemOfFileSystems} class allows to represent several fileSystems as an instance 9 | * of {@link FileSystem} interface. 10 | * 11 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 12 | * @version $Id: c30a0301af20bcb0f11de7f40e7e85456597ffc9 $ 13 | * @since 0.1 14 | */ 15 | @EqualsAndHashCode 16 | final class FileSystemOfFileSystems implements FileSystem { 17 | 18 | private final FileSystem[] fileSystems; 19 | 20 | FileSystemOfFileSystems(List fileSystems) { 21 | this(fileSystems.toArray(new FileSystem[] {})); 22 | } 23 | 24 | FileSystemOfFileSystems(FileSystem... fileSystems) { 25 | this.fileSystems = fileSystems; 26 | } 27 | 28 | @Override 29 | public List files() throws FileSystemException { 30 | List files = new ArrayList<>(); 31 | for (FileSystem fileSystem : fileSystems) { 32 | files.addAll(fileSystem.files()); 33 | } 34 | return files; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/FileSystemOfJarFile.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.IOException; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.zip.ZipEntry; 8 | import java.util.zip.ZipInputStream; 9 | import lombok.EqualsAndHashCode; 10 | 11 | /** 12 | * The {@link FileSystemOfJarFile} class allows to search files in given jar file. 13 | * 14 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 15 | * @version $Id: 93a9b6efa83c5340f38283dfc71ce97369e5983e $ 16 | * @since 0.1 17 | */ 18 | @EqualsAndHashCode 19 | final class FileSystemOfJarFile implements FileSystem { 20 | 21 | private final String jarPath; 22 | 23 | FileSystemOfJarFile(FileSystemPath jarPath) { 24 | this(jarPath.path().toString()); 25 | } 26 | 27 | FileSystemOfJarFile(String jarPath) { 28 | this.jarPath = jarPath; 29 | } 30 | 31 | @Override 32 | public List files() throws FileSystemException { 33 | try { 34 | List data = new ArrayList<>(); 35 | ZipInputStream zip = new ZipInputStream(new FileInputStream(jarPath)); 36 | for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip.getNextEntry()) { 37 | data.add(new FileSystemPathBase(entry.getName())); 38 | } 39 | return data; 40 | } catch (IOException e) { 41 | throw new FileSystemException(e); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/FileSystemOfJarFiles.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | import lombok.EqualsAndHashCode; 6 | 7 | /** 8 | * The {@link FileSystemOfJarFiles} class allows to convert a file system with JARs only to a file 9 | * system with files. Basically, it unzips files from the JARs and represents them as a separate 10 | * file system. 11 | * 12 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 13 | * @version $Id: ce639f91ae53ebd77ddc2a7fce048ded057c9f81 $ 14 | * @since 0.1 15 | */ 16 | @EqualsAndHashCode 17 | final class FileSystemOfJarFiles implements FileSystem { 18 | 19 | private final FileSystem fileSystem; 20 | private final Mapping mapping; 21 | 22 | FileSystemOfJarFiles(FileSystem fileSystem) { 23 | this( 24 | fileSystem, 25 | fs -> 26 | fs.files().stream() 27 | .map(FileSystemOfJarFile::new) 28 | .collect(Collectors.toList())); 29 | } 30 | 31 | private FileSystemOfJarFiles(FileSystem fileSystem, Mapping mapping) { 32 | this.fileSystem = fileSystem; 33 | this.mapping = mapping; 34 | } 35 | 36 | @Override 37 | public List files() throws FileSystemException { 38 | return new FileSystemOfFileSystems(mapping.objects(fileSystem)).files(); 39 | } 40 | 41 | @FunctionalInterface 42 | private interface Mapping { 43 | List objects(FileSystem fileSystem) throws FileSystemException; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/FileSystemOfPath.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.FileVisitResult; 5 | import java.nio.file.FileVisitor; 6 | import java.nio.file.Files; 7 | import java.nio.file.Path; 8 | import java.nio.file.attribute.BasicFileAttributes; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import lombok.EqualsAndHashCode; 12 | 13 | /** 14 | * The {@link FileSystemOfPath} class allows to search files by given path. 15 | * 16 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 17 | * @version $Id: 87a0d31e63c519070151300730b6825dcf916b83 $ 18 | * @since 0.1 19 | */ 20 | @EqualsAndHashCode 21 | final class FileSystemOfPath implements FileSystem { 22 | private final Path path; 23 | 24 | FileSystemOfPath(String path) { 25 | this(new FileSystemPathBase(path).path()); 26 | } 27 | 28 | FileSystemOfPath(Path path) { 29 | this.path = path; 30 | } 31 | 32 | @Override 33 | public List files() throws FileSystemException { 34 | try { 35 | List files = new ArrayList<>(); 36 | Files.walkFileTree( 37 | path, 38 | new FileVisitor() { 39 | @Override 40 | public FileVisitResult preVisitDirectory( 41 | Path dir, BasicFileAttributes attrs) { 42 | files.add(new FileSystemPathRelative(path, dir.toString())); 43 | return FileVisitResult.CONTINUE; 44 | } 45 | 46 | @Override 47 | public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { 48 | files.add(new FileSystemPathRelative(path, file.toString())); 49 | return FileVisitResult.CONTINUE; 50 | } 51 | 52 | @Override 53 | public FileVisitResult visitFileFailed(Path file, IOException exc) { 54 | return FileVisitResult.CONTINUE; 55 | } 56 | 57 | @Override 58 | public FileVisitResult postVisitDirectory(Path dir, IOException exc) { 59 | return FileVisitResult.CONTINUE; 60 | } 61 | }); 62 | return files; 63 | } catch (IOException e) { 64 | throw new FileSystemException(e); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/FileSystemPath.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.nio.file.Path; 4 | import java.nio.file.Paths; 5 | 6 | /** 7 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 8 | * @version $Id: dcf9d1b0ea73c354802e6fa01dfd8a150239b861 $ 9 | * @since 0.1 10 | */ 11 | public interface FileSystemPath { 12 | Path path(); 13 | 14 | boolean exist(); 15 | 16 | final class Fake implements FileSystemPath { 17 | 18 | private final Path path; 19 | private final boolean exist; 20 | 21 | public Fake() { 22 | this(Paths.get("."), false); 23 | } 24 | 25 | public Fake(String path) { 26 | this(Paths.get(path), false); 27 | } 28 | 29 | public Fake(String path, boolean exist) { 30 | this(Paths.get(path), exist); 31 | } 32 | 33 | public Fake(Path path, boolean exist) { 34 | this.path = path; 35 | this.exist = exist; 36 | } 37 | 38 | @Override 39 | public Path path() { 40 | return path; 41 | } 42 | 43 | @Override 44 | public boolean exist() { 45 | return exist; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/FileSystemPathBase.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.nio.file.Files; 4 | import java.nio.file.Path; 5 | import java.nio.file.Paths; 6 | import lombok.EqualsAndHashCode; 7 | import lombok.ToString; 8 | 9 | /** 10 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 11 | * @version $Id: 1aec0fba0c395900aaa386b4e71c38f7fa14f42b $ 12 | * @since 0.1 13 | */ 14 | @EqualsAndHashCode 15 | @ToString 16 | public class FileSystemPathBase implements FileSystemPath { 17 | 18 | private final Path directory; 19 | private final String file; 20 | 21 | public FileSystemPathBase(String path) { 22 | this(Paths.get(path)); 23 | } 24 | 25 | public FileSystemPathBase(String directory, String file) { 26 | this(Paths.get(directory), file); 27 | } 28 | 29 | public FileSystemPathBase(Path path) { 30 | this(path, ""); 31 | } 32 | 33 | public FileSystemPathBase(Directory directory, String fsPath) { 34 | this(directory.path(), fsPath); 35 | } 36 | 37 | public FileSystemPathBase(Path directory, String file) { 38 | this.directory = directory; 39 | this.file = file; 40 | } 41 | 42 | @Override 43 | public final Path path() { 44 | return directory.resolve(file); 45 | } 46 | 47 | @Override 48 | public final boolean exist() { 49 | return Files.exists(path()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/FileSystemPathRelative.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.nio.file.Path; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.ToString; 6 | 7 | /** 8 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 9 | * @version $Id: 1d758f7b06c0acb54c39021b38958f157731a588 $ 10 | * @since 0.1 11 | */ 12 | @EqualsAndHashCode 13 | @ToString(of = {"artifactPath"}) 14 | public class FileSystemPathRelative implements FileSystemPath { 15 | private final FileSystemPath fromPath; 16 | private final FileSystemPath artifactPath; 17 | 18 | public FileSystemPathRelative(Path fromPath, String artifactPath) { 19 | this(new FileSystemPathBase(fromPath), new FileSystemPathBase(artifactPath)); 20 | } 21 | 22 | public FileSystemPathRelative(String fromPath, String artifactPath) { 23 | this(new FileSystemPathBase(fromPath), new FileSystemPathBase(artifactPath)); 24 | } 25 | 26 | public FileSystemPathRelative(FileSystemPath fromPath, FileSystemPath artifactPath) { 27 | this.fromPath = fromPath; 28 | this.artifactPath = artifactPath; 29 | } 30 | 31 | @Override 32 | public final Path path() { 33 | if (fromPath.equals(artifactPath)) return artifactPath.path(); 34 | return fromPath.path().relativize(artifactPath.path()); 35 | } 36 | 37 | @Override 38 | public final boolean exist() { 39 | throw new UnsupportedOperationException( 40 | "Can't say definitely about existence of a path: " + path()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/Kernel.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * The {@link Kernel} interface declares a way to implement different xnit test runners. 9 | * 10 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 11 | * @version $Id: dc148560e6b1b3fe6849b7fa00aca336538f3259 $ 12 | * @since 0.2 13 | */ 14 | public interface Kernel { 15 | 16 | /** 17 | * Provides information about tests run. 18 | * 19 | * @return the status of a tests run 20 | * @throws KernelException if any error occurs 21 | */ 22 | Status status() throws KernelException; 23 | 24 | /** 25 | * Returns new instance of a kernel with provided listeners. 26 | * 27 | * @param listeners an instance (or instances) of kernel's listeners 28 | * @return the new instance of a kernel 29 | */ 30 | Kernel with(Listener... listeners); 31 | 32 | final class Fake implements Kernel { 33 | 34 | private final Status result; 35 | private final List listeners; 36 | 37 | /** 38 | * Constructs a new object. All listeners are stored internally. 39 | * 40 | * @param status a status of the execution 41 | */ 42 | public Fake(Status status) { 43 | this(status, new ArrayList<>()); 44 | } 45 | 46 | /** 47 | * Constructs a new object. 48 | * 49 | * @param status a status of the execution 50 | * @param availableListeners a list which will store all listeners 51 | */ 52 | public Fake(Status status, List availableListeners) { 53 | this.result = status; 54 | this.listeners = availableListeners; 55 | } 56 | 57 | @Override 58 | public Status status() { 59 | return this.result; 60 | } 61 | 62 | @Override 63 | public Kernel with(Object... objects) { 64 | this.listeners.addAll(Arrays.asList(objects)); 65 | return new Fake(this.result, this.listeners); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/KernelException.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | /** 4 | * The {@link KernelException} class is a default exception to handle errors which may occur in the 5 | * implementations of an {@link Kernel}. 6 | * 7 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 8 | * @version $Id: 53b5976b5e2d28b366eede297c16b5b25a19aa13 $ 9 | * @since 0.2 10 | */ 11 | public class KernelException extends SunshineException { 12 | public KernelException(String message) { 13 | super(message); 14 | } 15 | 16 | public KernelException(String message, Throwable cause) { 17 | super(message, cause); 18 | } 19 | 20 | public KernelException(Throwable cause) { 21 | super(cause); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/RegexCondition.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.regex.Pattern; 4 | import lombok.EqualsAndHashCode; 5 | 6 | /** 7 | * The implementation provides an ability to use a regex pattern for analyzing an identity. 8 | * 9 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 10 | * @version $Id: 499ac5f0e5319c5fb3073f70a2b7763c8a99bbca $ 11 | * @since 0.1 12 | */ 13 | @EqualsAndHashCode 14 | public class RegexCondition implements Condition { 15 | 16 | final Pattern regex; 17 | 18 | /** 19 | * Use a value of "tests-regex" system property as a regex pattern. If the system property is 20 | * not set, the "(.+)(Test)([\w\d]+)?" value is used. 21 | */ 22 | public RegexCondition() { 23 | this(System.getProperty("tests-regex", "(.+)(Test)([\\w\\d]+)?")); 24 | } 25 | 26 | /** 27 | * Construct the object with given regex. 28 | * 29 | * @param regex the value to be complied in a {@link Pattern} 30 | */ 31 | public RegexCondition(String regex) { 32 | this(Pattern.compile(regex)); 33 | } 34 | 35 | /** 36 | * Construct the object with given regex. 37 | * 38 | * @param regex the value 39 | */ 40 | public RegexCondition(Pattern regex) { 41 | this.regex = regex; 42 | } 43 | 44 | @Override 45 | public final boolean applicable(String identity) { 46 | return regex.matcher(identity).matches(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/SequentialExecution.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | 8 | /** 9 | * The class encapsulates several {@link Kernel}s and runs them sequentially. 10 | * 11 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 12 | * @version $Id: 0b867f69987e32f384686dc70ea2045108837e02 $ 13 | */ 14 | public class SequentialExecution implements Kernel { 15 | 16 | private final List> elements; 17 | 18 | @SafeVarargs 19 | public SequentialExecution(Kernel... kernels) { 20 | this(Arrays.asList(kernels)); 21 | } 22 | 23 | public SequentialExecution(List> kernels) { 24 | this.elements = kernels; 25 | } 26 | 27 | @Override 28 | public Status status() throws KernelException { 29 | final List results = new ArrayList<>(); 30 | for (Kernel kernel : this.elements) { 31 | results.add(kernel.status()); 32 | } 33 | return new CompositeStatus(results); 34 | } 35 | 36 | @Override 37 | public Kernel with(Listener... listeners) { 38 | return new SequentialExecution<>( 39 | this.elements.stream() 40 | .map(listenerKernel -> listenerKernel.with(listeners)) 41 | .collect(Collectors.toList())); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/Star.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | /** 4 | * The {@link Star} interface provides a contract to use {@link Kernel}s. The root idea is that a 5 | * {@link Star} can shine only it has a {@link Kernel}. And a {@link Kernel} is always a part of a 6 | * {@link Star}. 7 | * 8 | *

The interface is a top level abstraction of the Sunshine. 9 | * 10 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 11 | * @version $Id: 9953acd5fd7fa9e2279460f964c998a962d307a0 $ 12 | * @see Sun 13 | * @since 0.2 14 | */ 15 | @FunctionalInterface 16 | public interface Star { 17 | /** Allows this star to shine with an encapsulated {@link Kernel}(s). */ 18 | void shine(); 19 | } 20 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/Status.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | /** 4 | * The {@link Status} interface declares a way to retrieve tests run status. 5 | * 6 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 7 | * @version $Id: 3d30a6f228309abbda57ec02de1acaa4dd3b2580 $ 8 | * @since 0.2 9 | */ 10 | public interface Status { 11 | 12 | /** 13 | * Returns the exit code of an execution provided by xunit tests runner. 14 | * 15 | * @return the exit code 16 | */ 17 | short code(); 18 | 19 | /** 20 | * Returns a count of tests were run by a xunit runner. 21 | * 22 | * @return the count of total tests 23 | */ 24 | int runCount(); 25 | 26 | /** 27 | * Returns a count of failed tests were run by a xunit runner. 28 | * 29 | * @return the count of failed tests 30 | */ 31 | int failureCount(); 32 | 33 | /** 34 | * Returns a count of ignored or skipped tests were run by a xunit runner. 35 | * 36 | * @return the count of ignored tests 37 | */ 38 | int ignoreCount(); 39 | 40 | final class Fake implements Status { 41 | private final short c; 42 | private final int r; 43 | private final int f; 44 | private final int i; 45 | 46 | public Fake() { 47 | this((short) 0, 5, 0, 1); 48 | } 49 | 50 | public Fake(short code, int total, int failed, int ignored) { 51 | this.c = code; 52 | this.r = total; 53 | this.f = failed; 54 | this.i = ignored; 55 | } 56 | 57 | @Override 58 | public short code() { 59 | return this.c; 60 | } 61 | 62 | @Override 63 | public int runCount() { 64 | return this.r; 65 | } 66 | 67 | @Override 68 | public int failureCount() { 69 | return this.f; 70 | } 71 | 72 | @Override 73 | public int ignoreCount() { 74 | return this.i; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/Suite.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | /** 4 | * The interface represents some tests. 5 | * 6 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 7 | * @version $Id: 618be94d25190d11c2d8bcfb2fffe22ebd550fb8 $ 8 | * @since 0.1 9 | */ 10 | public interface Suite { 11 | 12 | /** 13 | * Returns tests from the suite. 14 | * 15 | * @return a test or tests 16 | * @throws SuiteException if some error occurs 17 | */ 18 | D tests() throws SuiteException; 19 | } 20 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/SuiteException.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | /** 4 | * The {@link SuiteException} class is a default exception to handle errors which may occur in the 5 | * implementations of a {@link Suite}. 6 | * 7 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 8 | * @version $Id: 42ae8454abc4c4fb31d8334a05aad2e46b3152f5 $ 9 | * @since 0.1 10 | */ 11 | public class SuiteException extends SunshineException { 12 | public SuiteException(String message) { 13 | super(message); 14 | } 15 | 16 | public SuiteException(String message, Throwable cause) { 17 | super(message, cause); 18 | } 19 | 20 | public SuiteException(Throwable cause) { 21 | super(cause); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/SuiteFromClasses.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.stream.Collectors; 6 | 7 | /** 8 | * The suite allows creation a test suite based on predefined classes. 9 | * 10 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 11 | * @version $Id: a853b6dc9b849393502308f627a6c850d2953ed6 $ 12 | */ 13 | public class SuiteFromClasses implements SunshineSuite { 14 | private final Class[] classes; 15 | 16 | /** 17 | * Construct new instance. 18 | * 19 | * @param clazz a class object (like {@code MyTest1.class}) 20 | */ 21 | public SuiteFromClasses(Class... clazz) { 22 | this.classes = clazz; 23 | } 24 | 25 | @Override 26 | public final List tests() throws SuiteException { 27 | return Arrays.stream(this.classes).map(TestFromClass::new).collect(Collectors.toList()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/SuiteFromFileSystem.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | 6 | /** 7 | * The class represents a suite of {@link SunshineTest}s which will be loaded based on given file 8 | * system. 9 | * 10 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 11 | * @version $Id: bc8b19ee17edab50e60a5afd7d39ff4667dac1e7 $ 12 | */ 13 | public class SuiteFromFileSystem implements SunshineSuite { 14 | private final FileSystem fileSystem; 15 | 16 | /** 17 | * Construct the new instance. 18 | * 19 | * @param fileSystem a file system to build a suite. Each item (path) will be represented by a 20 | * separate {@link SunshineTest}. 21 | */ 22 | public SuiteFromFileSystem(FileSystem fileSystem) { 23 | this.fileSystem = fileSystem; 24 | } 25 | 26 | @Override 27 | public final List tests() throws SuiteException { 28 | try { 29 | return fileSystem.files().stream() 30 | .map(f -> new TestFromFile(f.path().toString())) 31 | .collect(Collectors.toList()); 32 | } catch (FileSystemException e) { 33 | throw new SuiteException(e); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/Sun.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | /** 4 | * The {@link Sun} class provides an implementation of a {@link Star} especially designed for 5 | * continuous integration servers. If any errors occur during tests execution, a continuous 6 | * integration server will fail the job's execution. 7 | * 8 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 9 | * @version $Id: 953124c9929c2a318f9df440d831e8f14bb955b6 $ 10 | * @since 0.2 11 | */ 12 | public class Sun implements Star { 13 | 14 | private static final int SUNSHINE_ERROR = 12; 15 | private final Kernel core; 16 | 17 | /** 18 | * Constructs the new instance. 19 | * 20 | * @param kernel the {@link Kernel} 21 | */ 22 | public Sun(Kernel kernel) { 23 | this.core = kernel; 24 | } 25 | 26 | /** 27 | * Retrieves a {@link Status} of encapsulated {@link Kernel}. If there are some errors in 28 | * suite's preparation, the execution will be aborted with exit code #{@value SUNSHINE_ERROR}, 29 | * otherwise exit code will be provided by appropriate {@link Kernel}. 30 | */ 31 | @Override 32 | public final void shine() { 33 | try { 34 | final Status status = this.core.status(); 35 | System.out.println( 36 | new StringBuilder("\n===============================================\n") 37 | .append("Total tests run: ") 38 | .append(status.runCount()) 39 | .append(", Failures: ") 40 | .append(status.failureCount()) 41 | .append(", Skips: ") 42 | .append(status.ignoreCount()) 43 | .append("\n===============================================\n")); 44 | System.exit(status.code()); 45 | } catch (KernelException e) { 46 | e.printStackTrace(System.out); 47 | System.exit(Sun.SUNSHINE_ERROR); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/SunshineException.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | /** 4 | * The {@link SunshineException} class is a base exception for all Sunshine's exceptions. 5 | * 6 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 7 | * @version $Id: 5c527e02f26213a55981b35ac9ddc831fa6150a9 $ 8 | * @since 0.1 9 | */ 10 | public class SunshineException extends Exception { 11 | public SunshineException(String message) { 12 | super(message); 13 | } 14 | 15 | public SunshineException(String message, Throwable cause) { 16 | super(message, cause); 17 | } 18 | 19 | public SunshineException(Throwable cause) { 20 | super(cause); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/SunshineSuite.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | /** 7 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 8 | * @version $Id: d037c28a0c00f28630a0e653cf8581ed29a7a25a $ 9 | * @since 0.1 10 | */ 11 | public interface SunshineSuite extends Suite> { 12 | @Override 13 | List tests() throws SuiteException; 14 | 15 | final class Fake implements SunshineSuite { 16 | private final List tests; 17 | 18 | public Fake(SunshineTest... tests) { 19 | this.tests = Arrays.asList(tests); 20 | } 21 | 22 | @Override 23 | public List tests() { 24 | return tests; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/SunshineSuiteFilterable.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | 6 | /** 7 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 8 | * @version $Id: 8df6479d56cf0fb88269a9f3008ecabc0d8649b6 $ 9 | * @since 0.1 10 | */ 11 | public class SunshineSuiteFilterable implements SunshineSuite { 12 | 13 | private final SunshineSuite suite; 14 | private final Condition filter; 15 | 16 | public SunshineSuiteFilterable(SunshineSuite suite, Condition filter) { 17 | this.suite = suite; 18 | this.filter = filter; 19 | } 20 | 21 | @Override 22 | public final List tests() throws SuiteException { 23 | return suite.tests().stream() 24 | .filter(classTest -> classTest.match(filter)) 25 | .collect(Collectors.toList()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/SunshineSuitePrintable.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 7 | * @version $Id: 891ccf693413c3bbce5be36d557071422e363797 $ 8 | * @since 0.1 9 | */ 10 | public class SunshineSuitePrintable implements SunshineSuite { 11 | 12 | private final SunshineSuite sunshineSuite; 13 | 14 | public SunshineSuitePrintable(SunshineSuite sunshineSuite) { 15 | this.sunshineSuite = sunshineSuite; 16 | } 17 | 18 | @Override 19 | public final List tests() throws SuiteException { 20 | final List tests = this.sunshineSuite.tests(); 21 | final StringBuilder message = new StringBuilder(); 22 | message.append("Sunshine found ") 23 | .append(tests.size()) 24 | .append( 25 | " classes by the specified pattern. They all will be passed to appropriate xUnit engine.") 26 | .append("\nClasses:"); 27 | tests.forEach(c -> message.append("\n- ").append(c)); 28 | System.out.println(message); 29 | return tests; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/SunshineTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | /** 4 | * The interface represents a test like a Java class. 5 | * 6 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 7 | * @version $Id: 242540cd0d8ba8bdfc38d0d79ab6ca457697baab $ 8 | * @since 0.1 9 | */ 10 | public interface SunshineTest extends Test { 11 | @Override 12 | Class object() throws TestException; 13 | 14 | @Override 15 | boolean match(Condition condition); 16 | 17 | final class Fake implements SunshineTest { 18 | 19 | private final boolean matchCondition; 20 | 21 | public Fake() { 22 | this(false); 23 | } 24 | 25 | public Fake(boolean matchCondition) { 26 | this.matchCondition = matchCondition; 27 | } 28 | 29 | @Override 30 | public Class object() { 31 | return null; 32 | } 33 | 34 | @Override 35 | public boolean match(Condition condition) { 36 | return matchCondition; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/Test.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | /** 4 | * The interface represents a test like an generic object. 5 | * 6 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 7 | * @version $Id: 51857c3022100801dcebb8a8bba4d196d1bdce7c $ 8 | * @since 0.1 9 | */ 10 | public interface Test { 11 | T object() throws TestException; 12 | 13 | boolean match(Condition condition); 14 | 15 | class Fake implements Test { 16 | private final D d; 17 | private final boolean ruleAnswer; 18 | 19 | public Fake(D d, boolean ruleAnswer) { 20 | this.d = d; 21 | this.ruleAnswer = ruleAnswer; 22 | } 23 | 24 | @Override 25 | public D object() { 26 | return d; 27 | } 28 | 29 | @Override 30 | public boolean match(Condition condition) { 31 | return ruleAnswer; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/TestException.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | /** 4 | * The {@link TestException} class is a default exception to handle errors which may occur in the 5 | * implementations of a {@link Test} interface. 6 | * 7 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 8 | * @version $Id: 526c383e0cc1660a4133c2b2174e2e8af7f740a3 $ 9 | * @since 0.1 10 | */ 11 | public class TestException extends SunshineException { 12 | public TestException(String message) { 13 | super(message); 14 | } 15 | 16 | public TestException(String message, Throwable cause) { 17 | super(message, cause); 18 | } 19 | 20 | public TestException(Throwable cause) { 21 | super(cause); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/TestFromClass.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import lombok.EqualsAndHashCode; 4 | 5 | /** 6 | * The class represents a Java class as a test. 7 | * 8 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 9 | * @version $Id: 268cd0b7c07aa9a48f154d1e850eb0f17ec7a093 $ 10 | */ 11 | @EqualsAndHashCode 12 | public class TestFromClass implements SunshineTest { 13 | private final Class origin; 14 | 15 | /** 16 | * Construct the new instance. 17 | * 18 | * @param testClass a class to be treated as a test 19 | */ 20 | public TestFromClass(Class testClass) { 21 | this.origin = testClass; 22 | } 23 | 24 | @Override 25 | public final Class object() throws TestException { 26 | return this.origin; 27 | } 28 | 29 | @Override 30 | public final boolean match(Condition condition) { 31 | return condition.applicable(this.toString()); 32 | } 33 | 34 | @Override 35 | public final String toString() { 36 | return this.origin.getName(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/TestFromFile.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import lombok.EqualsAndHashCode; 4 | 5 | /** 6 | * The class represents a classpath file as a test in form of Java class. 7 | * 8 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 9 | * @version $Id: 272d58ee3e9f1cfaee40933324116cb777c9f6f4 $ 10 | */ 11 | @EqualsAndHashCode 12 | public class TestFromFile implements SunshineTest { 13 | private final String path; 14 | 15 | /** 16 | * Construct the new instance. 17 | * 18 | * @param path is a relative path in a file system which includes class name (like {@code 19 | * org/my/tests/Test1}). It has to be relative to current classpath. It can have {@code 20 | * .class} extension or not. 21 | */ 22 | public TestFromFile(String path) { 23 | this.path = path; 24 | } 25 | 26 | @Override 27 | public final Class object() throws TestException { 28 | try { 29 | return Class.forName(toString()); 30 | } catch (ClassNotFoundException e) { 31 | throw new TestException(e); 32 | } 33 | } 34 | 35 | @Override 36 | public final boolean match(Condition condition) { 37 | return condition.applicable(this.toString()); 38 | } 39 | 40 | @Override 41 | public final String toString() { 42 | return path.replaceAll("[/\\\\]", ".").replaceFirst("^\\.", "").replace(".class", ""); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/VerboseRegex.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.PrintStream; 4 | import java.util.Arrays; 5 | 6 | /** 7 | * The implementation allows printing of encapsulated condition to the standard output. The printing 8 | * will happen only once before the first usage of {@link #applicable(String)}. 9 | * 10 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 11 | * @version $Id: 53346cf21d6f99444d964013da18079433d82b66 $ 12 | * @since 0.3.0 13 | */ 14 | public class VerboseRegex implements Condition { 15 | 16 | private final RegexCondition regexCondition; 17 | private final boolean[] say = new boolean[] {true}; 18 | private final PrintStream printer; 19 | 20 | /** 21 | * Construct the object. 22 | * 23 | * @param condition the condition 24 | */ 25 | public VerboseRegex(RegexCondition condition) { 26 | this(condition, System.out); 27 | } 28 | 29 | /** 30 | * Construct the object. 31 | * 32 | * @param regexCondition the condition 33 | * @param printer a print stream 34 | */ 35 | VerboseRegex(RegexCondition regexCondition, PrintStream printer) { 36 | this.regexCondition = regexCondition; 37 | this.printer = printer; 38 | } 39 | 40 | @Override 41 | public final boolean applicable(String identity) { 42 | if (say[0]) { 43 | this.printer.println( 44 | String.format( 45 | "The following pattern will be used for classes filtering: %s", 46 | this.regexCondition.regex.pattern())); 47 | Arrays.fill(say, false); 48 | } 49 | return this.regexCondition.applicable(identity); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /sunshine-core/src/main/java/org/tatools/sunshine/core/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The core package of Sunshine. 3 | * 4 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 5 | * @version $Id: a4148ef99715401f2c5d9e9d7442b9bd99d6f8fb $ 6 | * @since 0.2 7 | */ 8 | package org.tatools.sunshine.core; 9 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/CompositeStatusTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.Arrays; 4 | import org.hamcrest.MatcherAssert; 5 | import org.hamcrest.Matchers; 6 | import org.junit.Test; 7 | 8 | /** 9 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 10 | * @version $Id: b1502cb51e9e05bafd0e02d42f49f30b90006c64 $ 11 | */ 12 | public class CompositeStatusTest { 13 | 14 | @Test 15 | public void testZeroCode() { 16 | MatcherAssert.assertThat( 17 | new CompositeStatus(Arrays.asList(new Status.Fake(), new Status.Fake())).code(), 18 | Matchers.is((short) 0)); 19 | } 20 | 21 | @Test 22 | public void testNonZeroPositiveCode() { 23 | MatcherAssert.assertThat( 24 | new CompositeStatus( 25 | Arrays.asList( 26 | new Status.Fake((short) 3, 0, 1, 1), 27 | new Status.Fake((short) 2, 0, 1, 1))) 28 | .code(), 29 | Matchers.is((short) 3)); 30 | } 31 | 32 | @Test 33 | public void testNonZeroNegativeCode() { 34 | MatcherAssert.assertThat( 35 | new CompositeStatus( 36 | Arrays.asList( 37 | new Status.Fake((short) -3, 0, 1, 1), 38 | new Status.Fake((short) 0, 0, 1, 1))) 39 | .code(), 40 | Matchers.is((short) -3)); 41 | } 42 | 43 | @Test 44 | public void testSumOfRunCount() { 45 | MatcherAssert.assertThat( 46 | new CompositeStatus( 47 | Arrays.asList( 48 | new Status.Fake((short) 3, 1, 2, 3), 49 | new Status.Fake((short) 2, 4, 5, 6))) 50 | .runCount(), 51 | Matchers.is(5)); 52 | } 53 | 54 | @Test 55 | public void testSumOfFailureCount() { 56 | MatcherAssert.assertThat( 57 | new CompositeStatus( 58 | Arrays.asList( 59 | new Status.Fake((short) 3, 1, 2, 3), 60 | new Status.Fake((short) 2, 4, 5, 6))) 61 | .failureCount(), 62 | Matchers.is(7)); 63 | } 64 | 65 | @Test 66 | public void testSumOfIgnoreCount() { 67 | MatcherAssert.assertThat( 68 | new CompositeStatus( 69 | Arrays.asList( 70 | new Status.Fake((short) 3, 1, 2, 3), 71 | new Status.Fake((short) 2, 4, 5, 6))) 72 | .ignoreCount(), 73 | Matchers.is(9)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/DirectoryBaseTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Paths; 5 | import org.hamcrest.MatcherAssert; 6 | import org.hamcrest.Matchers; 7 | import org.junit.Rule; 8 | import org.junit.Test; 9 | import org.junit.rules.TemporaryFolder; 10 | 11 | /** 12 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 13 | * @version $Id: 17ffe2b35677c4fd40b0496ccdeee42c29f4f9c4 $ 14 | * @since 0.1 15 | */ 16 | public class DirectoryBaseTest { 17 | 18 | @Rule public TemporaryFolder testFolder = new TemporaryFolder(); 19 | 20 | @Test 21 | public void create() throws IOException { 22 | final FileSystemPathBase path = 23 | new FileSystemPathBase(testFolder.getRoot().getAbsolutePath(), "a"); 24 | new DirectoryBase(path).create(); 25 | MatcherAssert.assertThat("The directory wasn't created", path.exist()); 26 | } 27 | 28 | @Test 29 | public void remove() throws IOException { 30 | java.io.File file = testFolder.newFolder(); 31 | final FileSystemPathBase path = new FileSystemPathBase(file.toString()); 32 | new DirectoryBase(path).remove(); 33 | MatcherAssert.assertThat("The directory exists", !path.exist()); 34 | } 35 | 36 | @Test 37 | public void exist() { 38 | MatcherAssert.assertThat( 39 | "The directory isn't present", 40 | new DirectoryBase(new FileSystemPathBase(testFolder.getRoot().getAbsolutePath())) 41 | .exist()); 42 | } 43 | 44 | @Test 45 | public void path() { 46 | final String path = "a"; 47 | MatcherAssert.assertThat(new DirectoryBase(path).path(), Matchers.equalTo(Paths.get(path))); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/DirectoryWithAutomaticCreationTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.IOException; 4 | import org.hamcrest.MatcherAssert; 5 | import org.junit.Rule; 6 | import org.junit.Test; 7 | import org.junit.rules.TemporaryFolder; 8 | 9 | /** 10 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 11 | * @version $Id: 716a5742c4cc3cbc73571cd7cfb2621ec2bba1cc $ 12 | * @since 0.1 13 | */ 14 | public class DirectoryWithAutomaticCreationTest { 15 | @Rule public TemporaryFolder testFolder = new TemporaryFolder(); 16 | 17 | @Test 18 | public void create() throws IOException { 19 | final FileSystemPathBase path = 20 | new FileSystemPathBase(testFolder.newFolder().toString(), "a"); 21 | new DirectoryWithAutomaticCreation(new DirectoryBase(path)).create(); 22 | MatcherAssert.assertThat("The directory wasn't created", path.exist()); 23 | } 24 | 25 | @Test 26 | public void remove() throws IOException { 27 | final FileSystemPathBase path = new FileSystemPathBase(testFolder.newFolder().toString()); 28 | new DirectoryWithAutomaticCreation(new DirectoryBase(path)).remove(); 29 | MatcherAssert.assertThat("The directory wasn't removed", !path.exist()); 30 | } 31 | 32 | @Test 33 | public void exist() throws IOException { 34 | final FileSystemPathBase path = 35 | new FileSystemPathBase(testFolder.newFolder().toString(), "a"); 36 | new DirectoryWithAutomaticCreation(new DirectoryBase(path)).exist(); 37 | MatcherAssert.assertThat("The directory wasn't created", path.exist()); 38 | } 39 | 40 | @Test 41 | public void path() throws IOException { 42 | final FileSystemPathBase path = 43 | new FileSystemPathBase(testFolder.newFolder().toString(), "a"); 44 | new DirectoryWithAutomaticCreation(new DirectoryBase(path)).path(); 45 | MatcherAssert.assertThat("The directory wasn't created", path.exist()); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/DirectoryWithAutomaticDeletionTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Path; 5 | import org.hamcrest.MatcherAssert; 6 | import org.hamcrest.Matchers; 7 | import org.junit.Rule; 8 | import org.junit.Test; 9 | import org.junit.rules.TemporaryFolder; 10 | 11 | /** 12 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 13 | * @version $Id: ddf030c80df4f4f71a3153c1b8a961d1fda3ef1b $ 14 | * @since 0.1 15 | */ 16 | public class DirectoryWithAutomaticDeletionTest { 17 | @Rule public TemporaryFolder testFolder = new TemporaryFolder(); 18 | 19 | @Test 20 | public void create() throws IOException { 21 | final java.io.File file = testFolder.getRoot(); 22 | new DirectoryWithAutomaticDeletion(new Directory.Fake(file.toPath())).create(); 23 | MatcherAssert.assertThat("The directory wasn't created", file.exists()); 24 | } 25 | 26 | @Test 27 | public void remove() throws IOException { 28 | final java.io.File file = testFolder.getRoot(); 29 | new DirectoryWithAutomaticDeletion(new Directory.Fake(file.toPath())).remove(); 30 | MatcherAssert.assertThat("The directory exists", file.exists()); 31 | } 32 | 33 | @Test 34 | public void exist() { 35 | MatcherAssert.assertThat( 36 | "The directory isn't present", 37 | new DirectoryWithAutomaticDeletion( 38 | new Directory.Fake(testFolder.getRoot().toPath(), true)) 39 | .exist()); 40 | } 41 | 42 | @Test 43 | public void path() { 44 | final Path file = testFolder.getRoot().toPath(); 45 | MatcherAssert.assertThat( 46 | new DirectoryWithAutomaticDeletion(new Directory.Fake(file)).path(), 47 | Matchers.equalTo(file)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/FileBaseTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.IOException; 4 | import java.nio.file.Files; 5 | import org.hamcrest.MatcherAssert; 6 | import org.hamcrest.Matchers; 7 | import org.junit.Rule; 8 | import org.junit.Test; 9 | import org.junit.rules.TemporaryFolder; 10 | 11 | /** 12 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 13 | * @version $Id: ed13d9496c5a71904dc82edd0c49ed6ac7706f1d $ 14 | * @since 0.1 15 | */ 16 | public class FileBaseTest { 17 | @Rule public TemporaryFolder testFolder = new TemporaryFolder(); 18 | 19 | @Test 20 | public void write() throws IOException { 21 | final FileBase file = new FileBase(testFolder.getRoot().getAbsolutePath(), "ccc"); 22 | file.write("dasd"); 23 | MatcherAssert.assertThat(Files.exists(file.path()), Matchers.is(true)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/FileSystemFilteredTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.Collections; 4 | import org.hamcrest.MatcherAssert; 5 | import org.hamcrest.Matchers; 6 | import org.junit.Test; 7 | 8 | /** 9 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 10 | * @version $Id: d438706dcd72ae906bace9bb4f1244f71a1f07ed $ 11 | * @since 0.1 12 | */ 13 | public class FileSystemFilteredTest { 14 | @Test 15 | public void files() throws FileSystemException { 16 | MatcherAssert.assertThat( 17 | new FileSystemFiltered( 18 | new FileSystem.Fake( 19 | Collections.singletonList(new FileSystemPath.Fake())), 20 | new Condition.Fake(false)) 21 | .files(), 22 | Matchers.hasSize(0)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/FileSystemOfClassesTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.Arrays; 4 | import org.hamcrest.MatcherAssert; 5 | import org.hamcrest.Matchers; 6 | import org.junit.Test; 7 | 8 | /** 9 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 10 | * @version $Id: d9b178f1515b8b4e5f4d597a34989cdb3e888b67 $ 11 | * @since 0.1 12 | */ 13 | public class FileSystemOfClassesTest { 14 | @Test 15 | public void onlyFilesInFileSystem() throws FileSystemException { 16 | MatcherAssert.assertThat( 17 | new FileSystemOfClasses( 18 | new FileSystem.Fake( 19 | Arrays.asList( 20 | new FileSystemPath.Fake("SomeTest.class"), 21 | new FileSystemPath.Fake("some-file.txt")))) 22 | .files(), 23 | Matchers.hasSize(1)); 24 | } 25 | 26 | @Test 27 | public void filesAndJarsInFileSystem() throws FileSystemException { 28 | MatcherAssert.assertThat( 29 | new FileSystemOfClasses(new FileSystemOfJarFile("build/sample-tests.jar")).files(), 30 | Matchers.hasSize(5)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/FileSystemOfClasspathClassesTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import org.hamcrest.MatcherAssert; 4 | import org.hamcrest.Matchers; 5 | import org.junit.Test; 6 | 7 | /** 8 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 9 | * @version $Id: f5131866bb0027bb8a34fc0a89ed1bd122f8e26f $ 10 | * @since 0.1 11 | */ 12 | public class FileSystemOfClasspathClassesTest { 13 | 14 | @Test 15 | public void files() throws FileSystemException { 16 | MatcherAssert.assertThat( 17 | new FileSystemOfClasspathClasses().files(), Matchers.not(Matchers.empty())); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/FileSystemOfFileSystemsTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collections; 5 | import java.util.List; 6 | import org.hamcrest.MatcherAssert; 7 | import org.hamcrest.Matchers; 8 | import org.junit.Test; 9 | 10 | /** 11 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 12 | * @version $Id: 3e5bad1084337a53e8f997ce2d88f6d4feda6bb5 $ 13 | * @since 0.1 14 | */ 15 | public class FileSystemOfFileSystemsTest { 16 | @Test 17 | public void files() throws FileSystemException { 18 | List fileSystems = 19 | Arrays.asList( 20 | new FileSystem.Fake(Collections.singletonList(new FileSystemPath.Fake())), 21 | new FileSystem.Fake(Collections.singletonList(new FileSystemPath.Fake()))); 22 | MatcherAssert.assertThat( 23 | new FileSystemOfFileSystems(fileSystems).files(), Matchers.hasSize(2)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/FileSystemOfJarFileTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import org.hamcrest.MatcherAssert; 4 | import org.hamcrest.Matchers; 5 | import org.junit.Test; 6 | 7 | /** 8 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 9 | * @version $Id: 3c4625a55e7905cb4defbff0a7d4ef5d90d8fad1 $ 10 | * @since 0.1 11 | */ 12 | public class FileSystemOfJarFileTest { 13 | @Test 14 | public void files() throws FileSystemException { 15 | MatcherAssert.assertThat( 16 | new FileSystemOfJarFile("build/sample-tests.jar").files(), 17 | Matchers.hasItem(new FileSystemPathBase("org/tatools/testng/Test1.class"))); 18 | } 19 | 20 | @Test(expected = FileSystemException.class) 21 | public void incorrectPath() throws FileSystemException { 22 | new FileSystemOfJarFile("faffasfas").files(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/FileSystemOfJarFilesTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import org.hamcrest.MatcherAssert; 4 | import org.hamcrest.Matchers; 5 | import org.junit.Test; 6 | 7 | /** 8 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 9 | * @version $Id: 0b6234fae86296197210970f8b08c0cd52c587b0 $ 10 | * @since 0.1 11 | */ 12 | public class FileSystemOfJarFilesTest { 13 | @Test 14 | public void files() throws FileSystemException { 15 | MatcherAssert.assertThat( 16 | new FileSystemOfJarFiles( 17 | new FileSystem.Fake( 18 | new FileSystemPath.Fake("build/sample-tests.jar"), 19 | new FileSystemPath.Fake("build/sample-tests.jar"))) 20 | .files(), 21 | Matchers.hasSize(20)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/FileSystemOfPathTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import org.hamcrest.CustomTypeSafeMatcher; 4 | import org.hamcrest.MatcherAssert; 5 | import org.hamcrest.Matchers; 6 | import org.junit.Test; 7 | 8 | /** 9 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 10 | * @version $Id: d68c89e993e6067b8b7452e7b66e820bd7174447 $ 11 | * @since 0.1 12 | */ 13 | public class FileSystemOfPathTest { 14 | 15 | private static final String RESOURCES = "src/test/java"; 16 | 17 | @Test 18 | public void files() throws FileSystemException { 19 | CustomTypeSafeMatcher matcher = 20 | new CustomTypeSafeMatcher("Has at least one item") { 21 | @Override 22 | protected boolean matchesSafely(Integer item) { 23 | return item > 0; 24 | } 25 | }; 26 | MatcherAssert.assertThat( 27 | new FileSystemOfPath(RESOURCES).files(), Matchers.hasSize(matcher)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/FileSystemPathBaseTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.nio.file.Paths; 4 | import org.hamcrest.MatcherAssert; 5 | import org.hamcrest.Matchers; 6 | import org.junit.Test; 7 | 8 | /** 9 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 10 | * @version $Id: 74f658e96237f894691fe3e15ea08f3a26f5f3e6 $ 11 | * @since 0.1 12 | */ 13 | public class FileSystemPathBaseTest { 14 | 15 | @Test 16 | public void path() { 17 | final String path = "aa"; 18 | MatcherAssert.assertThat( 19 | new FileSystemPathBase(path).path(), Matchers.equalTo(Paths.get(path))); 20 | } 21 | 22 | @Test 23 | public void pathWithFolder() { 24 | final String directory = "aa"; 25 | final String file = "file"; 26 | MatcherAssert.assertThat( 27 | new FileSystemPathBase(directory, file).path(), 28 | Matchers.equalTo(Paths.get(directory + "/" + file))); 29 | } 30 | 31 | @Test 32 | public void exist() { 33 | MatcherAssert.assertThat( 34 | "File is absent", 35 | new FileSystemPathBase( 36 | "src/main/java/org/tatools/sunshine/core/FileSystemPathBase.java") 37 | .exist()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/FileSystemPathRelativeTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.nio.file.Path; 4 | import java.nio.file.Paths; 5 | import org.hamcrest.CustomTypeSafeMatcher; 6 | import org.hamcrest.MatcherAssert; 7 | import org.hamcrest.Matchers; 8 | import org.junit.Test; 9 | 10 | /** 11 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 12 | * @version $Id: 94713306b64e827afca6199dfea4c1be5ea5fd23 $ 13 | * @since 0.1 14 | */ 15 | public class FileSystemPathRelativeTest { 16 | 17 | @Test 18 | public void asStringForParentWithSlashInTheEnd() { 19 | MatcherAssert.assertThat( 20 | new FileSystemPathRelative("/a/b/", "/a/b/c").path(), 21 | Matchers.is(new PathMatcher("c"))); 22 | } 23 | 24 | @Test 25 | public void asStringForParentWithoutSlashInTheEnd() { 26 | MatcherAssert.assertThat( 27 | new FileSystemPathRelative("/a/b", "/a/b/c").path(), 28 | Matchers.is(new PathMatcher("c"))); 29 | } 30 | 31 | @Test 32 | public void asStringWhenParentIsEqualsToFull() { 33 | MatcherAssert.assertThat( 34 | new FileSystemPathRelative("/a/b/c", "/a/b/c").path(), 35 | Matchers.is(new PathMatcher("/a/b/c"))); 36 | } 37 | 38 | @Test 39 | public void asStringForRelativeParentWithSlashInTheEnd() { 40 | MatcherAssert.assertThat( 41 | new FileSystemPathRelative("a/b/", "a/b/c").path(), 42 | Matchers.is(new PathMatcher("c"))); 43 | } 44 | 45 | @Test 46 | public void asStringForRelativeParentWithoutSlashInTheEnd() { 47 | MatcherAssert.assertThat( 48 | new FileSystemPathRelative("a/b", "a/b/c").path(), 49 | Matchers.is(new PathMatcher("c"))); 50 | } 51 | 52 | private final class PathMatcher extends CustomTypeSafeMatcher { 53 | 54 | private final String expected; 55 | 56 | PathMatcher(String expected) { 57 | super(expected); 58 | this.expected = expected; 59 | } 60 | 61 | @Override 62 | protected boolean matchesSafely(Path item) { 63 | return item.equals(Paths.get(expected)); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/RegexConditionTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | import org.hamcrest.MatcherAssert; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.junit.runners.Parameterized; 9 | 10 | /** 11 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 12 | * @version $Id: 0f6c3f7f5275afc4e9eabf1f221936bced8294cb $ 13 | * @since 0.1 14 | */ 15 | @RunWith(Parameterized.class) 16 | public class RegexConditionTest { 17 | 18 | private final String className; 19 | 20 | public RegexConditionTest(String className) { 21 | this.className = className; 22 | } 23 | 24 | @Parameterized.Parameters 25 | public static Collection data() { 26 | return Arrays.asList( 27 | new Object[][] { 28 | {"io.github.my.FirstTest"}, 29 | {"io.github.my.FirstTest1"}, 30 | {"io.github.my.Test"}, 31 | {"io.github.my.1Test"}, 32 | {"io.github.my.FirstTestDo"}, 33 | }); 34 | } 35 | 36 | @Test 37 | public void applicable() { 38 | MatcherAssert.assertThat( 39 | "Regex doesn't work for " + this.className, 40 | new RegexCondition().applicable(this.className)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/SequentialExecutionTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import org.hamcrest.MatcherAssert; 6 | import org.hamcrest.Matchers; 7 | import org.junit.Test; 8 | 9 | /** 10 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 11 | * @version $Id: e70813251cc17c2e3e7945879bfaf32c4a806544 $ 12 | */ 13 | public class SequentialExecutionTest { 14 | 15 | @Test 16 | public void testStatus() throws KernelException { 17 | MatcherAssert.assertThat( 18 | new SequentialExecution( 19 | new Kernel.Fake(new Status.Fake()), 20 | new Kernel.Fake(new Status.Fake((short) 1, 2, 1, 1))) 21 | .status() 22 | .code(), 23 | Matchers.is((short) 1)); 24 | } 25 | 26 | @Test 27 | public void testWithListeners() { 28 | final List listeners = new ArrayList<>(); 29 | new SequentialExecution(new Kernel.Fake(new Status.Fake(), listeners)) 30 | .with(new Object()); 31 | MatcherAssert.assertThat(listeners, Matchers.hasSize(1)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/SuiteFromClassesTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import org.hamcrest.MatcherAssert; 4 | import org.hamcrest.Matchers; 5 | import org.junit.Test; 6 | 7 | /** 8 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 9 | * @version $Id: c6741c2b14762195d1061c99b5fe30ec2ab28750 $ 10 | */ 11 | public class SuiteFromClassesTest { 12 | 13 | @Test 14 | public void tests() throws SuiteException { 15 | MatcherAssert.assertThat( 16 | new SuiteFromClasses(SuiteFromClasses.class).tests(), Matchers.hasSize(1)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/SuiteFromFileSystemTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import org.hamcrest.MatcherAssert; 4 | import org.hamcrest.Matchers; 5 | import org.junit.Test; 6 | 7 | /** 8 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 9 | * @version $Id: 181837c51a2b1e8ce35fb66d2a9d672317bb99cc $ 10 | */ 11 | public class SuiteFromFileSystemTest { 12 | 13 | @Test 14 | public void tests() throws SuiteException { 15 | MatcherAssert.assertThat( 16 | new SuiteFromFileSystem(new FileSystem.Fake(new FileSystemPath.Fake("a"))).tests(), 17 | Matchers.hasSize(1)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/SunTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import org.junit.Rule; 4 | import org.junit.Test; 5 | import org.junit.contrib.java.lang.system.ExpectedSystemExit; 6 | import org.tatools.sunshine.core.Status.Fake; 7 | 8 | /** 9 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 10 | * @version $Id: aeaa266b5664152319f3169c4440f298e1f63235 $ 11 | * @since 0.2 12 | */ 13 | public class SunTest { 14 | @Rule public final ExpectedSystemExit exit = ExpectedSystemExit.none(); 15 | 16 | @Test 17 | public void shine() { 18 | exit.expectSystemExitWithStatus(0); 19 | new Sun(new Kernel.Fake(new Fake())).shine(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/SunshineSuitePrintableTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import org.hamcrest.MatcherAssert; 4 | import org.hamcrest.Matchers; 5 | import org.junit.Test; 6 | 7 | /** 8 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 9 | * @version $Id: 5606f09345366e8aca166089d64beb8e145ecc4e $ 10 | * @since 0.1 11 | */ 12 | public class SunshineSuitePrintableTest { 13 | 14 | @Test 15 | public void tests() throws SuiteException { 16 | final SunshineTest.Fake test = new SunshineTest.Fake(); 17 | MatcherAssert.assertThat( 18 | new SunshineSuitePrintable(new SunshineSuite.Fake(test)).tests(), 19 | Matchers.contains(test)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/TestFromClassTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import org.hamcrest.MatcherAssert; 4 | import org.hamcrest.Matchers; 5 | import org.junit.Test; 6 | 7 | /** 8 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 9 | * @version $Id: 8408a9f3f288b925b5900a54f2d9f08e1cce1c80 $ 10 | */ 11 | public class TestFromClassTest { 12 | 13 | @Test 14 | public void testObject() throws TestException { 15 | MatcherAssert.assertThat( 16 | new TestFromClass(TestFromClass.class).object(), 17 | Matchers.equalTo(TestFromClass.class)); 18 | } 19 | 20 | @Test 21 | public void testToString() { 22 | MatcherAssert.assertThat( 23 | new TestFromClass(TestFromClass.class).toString(), 24 | Matchers.equalTo("org.tatools.sunshine.core.TestFromClass")); 25 | } 26 | 27 | @Test 28 | public void testFilter() { 29 | MatcherAssert.assertThat( 30 | new TestFromClass(TestFromClass.class) 31 | .match("org.tatools.sunshine.core.TestFromClass"::equals), 32 | Matchers.is(true)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/TestFromFileTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import org.hamcrest.MatcherAssert; 4 | import org.hamcrest.Matchers; 5 | import org.junit.Test; 6 | 7 | /** 8 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 9 | * @version $Id: 3677f68b5cbe546532944301f3c98cc18822cc5a $ 10 | */ 11 | public class TestFromFileTest { 12 | 13 | @Test 14 | public void object() throws TestException { 15 | MatcherAssert.assertThat( 16 | new TestFromFile("org/tatools/sunshine/core/TestFromFile.class").object(), 17 | Matchers.equalTo(TestFromFile.class)); 18 | } 19 | 20 | @Test 21 | public void testToStringWithClassExtension() { 22 | MatcherAssert.assertThat( 23 | new TestFromFile("org/tatools/sunshine/core/TestFromFile.class").toString(), 24 | Matchers.equalTo("org.tatools.sunshine.core.TestFromFile")); 25 | } 26 | 27 | @Test 28 | public void testToStringWithoutClassExtension() { 29 | MatcherAssert.assertThat( 30 | new TestFromFile("org/tatools/sunshine/core/TestFromFile").toString(), 31 | Matchers.equalTo("org.tatools.sunshine.core.TestFromFile")); 32 | } 33 | 34 | @Test 35 | public void testFilter() { 36 | MatcherAssert.assertThat( 37 | new TestFromFile("org/tatools/sunshine/core/TestFromFile") 38 | .match("org.tatools.sunshine.core.TestFromFile"::equals), 39 | Matchers.is(true)); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /sunshine-core/src/test/java/org/tatools/sunshine/core/VerboseRegexTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.core; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.PrintStream; 5 | import org.hamcrest.MatcherAssert; 6 | import org.hamcrest.Matchers; 7 | import org.junit.Test; 8 | 9 | /** 10 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 11 | * @version $Id: de03b643fd398d84899b9a8929ba57a3fa224ccc $ 12 | * @since 0.3.0 13 | */ 14 | public class VerboseRegexTest { 15 | 16 | @Test 17 | public void testIfMessageIsDisplayedOnce() { 18 | final ByteArrayOutputStream result = new ByteArrayOutputStream(); 19 | final VerboseRegex regex = 20 | new VerboseRegex(new RegexCondition("ddd"), new PrintStream(result)); 21 | regex.applicable("a"); 22 | regex.applicable("b"); 23 | MatcherAssert.assertThat( 24 | new String(result.toByteArray()), 25 | Matchers.is("The following pattern will be used for classes filtering: ddd\n")); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sunshine-junit4-integration-tests/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | } 5 | dependencies { 6 | classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.3' 7 | } 8 | } 9 | 10 | apply plugin: 'com.github.johnrengelman.shadow' 11 | 12 | dependencies { 13 | jar { 14 | manifest { 15 | attributes 'Main-Class': 'org.tatools.sunshine.junit4.Sunshine' 16 | attributes "Class-Path": configurations.runtime.collect { 17 | "deps/" + it.getName() 18 | }.join(' ') 19 | } 20 | } 21 | } 22 | 23 | task storeDependencies(type: Copy) { 24 | into "$buildDir/libs/deps" 25 | from configurations.runtime 26 | } 27 | 28 | build.dependsOn(storeDependencies) 29 | 30 | task runIntegrationTests { Task task -> 31 | doLast { 32 | task.project.exec { 33 | executable "sh" 34 | args "-c", "cd build/libs/ && java -jar ${project.name}-${version}.jar " + 35 | "| grep \"Total tests run: 1, Failures: 0, Skips: 0\"" 36 | } 37 | task.project.exec { 38 | executable "sh" 39 | args "-c", "cd build/libs/ && " + 40 | "java -Dtests-regex=\"(org.tatools.junit4tests)(.+)?\" -jar ${project.name}-${version}-all.jar " + 41 | "| grep \"Total tests run: 1, Failures: 0, Skips: 0\"" 42 | } 43 | } 44 | } 45 | runIntegrationTests.dependsOn(build) 46 | runIntegrationTests.dependsOn(shadowJar) 47 | 48 | task ready(dependsOn: runIntegrationTests) { 49 | doLast { 50 | println("Sunshine JUnit 4 integration testing is completed.") 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /sunshine-junit4-integration-tests/src/main/java/org/tatools/junit4tests/PassedTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.junit4tests; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 7 | * @version $Id: 6f92dabee8e08694ebdf3e3a807885a3d71543be $ 8 | * @since 0.1 9 | */ 10 | public class PassedTest { 11 | @Test 12 | public void test() {} 13 | } 14 | -------------------------------------------------------------------------------- /sunshine-junit4-integration-tests/src/main/java/org/tatools/junit4tests/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The package is used to hold the classes for integration testing of the sunshine-junit4. 3 | * 4 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 5 | * @version $Id: 9a601224a24dc38d5049056b682dab18d0794cf3 $ 6 | * @since 0.2 7 | */ 8 | package org.tatools.junit4tests; 9 | -------------------------------------------------------------------------------- /sunshine-junit4/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compileOnly 'org.projectlombok:lombok:1.16.14' 3 | annotationProcessor 'org.projectlombok:lombok:1.16.14' 4 | compile 'junit:junit:4.11' 5 | testCompile 'org.hamcrest:hamcrest-all:1.3' 6 | } 7 | 8 | task ready(dependsOn: check) { 9 | doLast { 10 | println("Unit testing of Sunshine JUnit 4 is completed.") 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /sunshine-junit4/gradle.properties: -------------------------------------------------------------------------------- 1 | NAME="Sunshine JUnit 4 adapter" 2 | DESCRIPTION="The package is Sunshine's adapter for JUnit 4 tests runner." 3 | -------------------------------------------------------------------------------- /sunshine-junit4/src/main/java/org/tatools/sunshine/junit4/Junit4Kernel.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.junit4; 2 | 3 | import java.util.Arrays; 4 | import org.junit.runner.Computer; 5 | import org.junit.runner.JUnitCore; 6 | import org.junit.runner.notification.RunListener; 7 | import org.tatools.sunshine.core.*; 8 | 9 | /** 10 | * The class provides a {@link Kernel} implementation of JUnit runner. 11 | * 12 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 13 | * @version $Id: 04eb2e2905c6219027a4ed945d6cbac74c6d54ec $ 14 | * @since 0.1 15 | */ 16 | public class Junit4Kernel implements Kernel { 17 | 18 | private final JUnitCore junit; 19 | private final Suite[]> suiteForRun; 20 | 21 | /** 22 | * Initializes a newly created {@link Junit4Kernel} object so that it represents an JUnit 4 23 | * runner. 24 | * 25 | * @param suite the tests suite 26 | */ 27 | public Junit4Kernel(Suite[]> suite) { 28 | this(new JUnitCore(), suite); 29 | } 30 | 31 | private Junit4Kernel(JUnitCore jUnitCore, Suite[]> suite) { 32 | this.junit = jUnitCore; 33 | this.suiteForRun = suite; 34 | } 35 | 36 | /** 37 | * Returns status of JUnite tests execution. 38 | * 39 | * @return the status 40 | * @throws KernelException if any error occurs during JUnit tests execution. 41 | */ 42 | @Override 43 | public final Status status() throws KernelException { 44 | try { 45 | return new JunitStatus(this.junit.run(new Computer(), this.suiteForRun.tests())); 46 | } catch (SuiteException e) { 47 | throw new KernelException("Some problem occurs in the JUnit 4 kernel", e); 48 | } 49 | } 50 | 51 | /** 52 | * Returns new instance of the JUnit kernel with provided listeners. 53 | * 54 | * @param listeners an instance (or instances) of JUnit listeners 55 | * @return the new instance of the JUnit kernel 56 | */ 57 | @Override 58 | public final Junit4Kernel with(RunListener... listeners) { 59 | final JUnitCore jUnitCore = new JUnitCore(); 60 | Arrays.stream(listeners).forEach(jUnitCore::addListener); 61 | return new Junit4Kernel(jUnitCore, this.suiteForRun); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /sunshine-junit4/src/main/java/org/tatools/sunshine/junit4/JunitStatus.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.junit4; 2 | 3 | import org.junit.runner.Result; 4 | import org.tatools.sunshine.core.Status; 5 | 6 | /** 7 | * The class provides an implementation of the {@link Status} of JUnit execution. 8 | * 9 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 10 | * @version $Id: f364d89a627aedad73e33b009dc3e450afcc405f $ 11 | * @since 0.2 12 | */ 13 | public class JunitStatus implements Status { 14 | 15 | private final Result status; 16 | 17 | /** 18 | * Initializes a newly created {@link JunitStatus} object so that it represents a status of 19 | * JUnit 4 execution. 20 | * 21 | * @param result the JUnit 4 result 22 | */ 23 | public JunitStatus(Result result) { 24 | this.status = result; 25 | } 26 | 27 | @Override 28 | public final short code() { 29 | if (this.status.wasSuccessful()) { 30 | return (short) 0; 31 | } 32 | return (short) 1; 33 | } 34 | 35 | @Override 36 | public final int runCount() { 37 | return status.getRunCount(); 38 | } 39 | 40 | @Override 41 | public final int failureCount() { 42 | return status.getFailureCount(); 43 | } 44 | 45 | @Override 46 | public final int ignoreCount() { 47 | return status.getIgnoreCount(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /sunshine-junit4/src/main/java/org/tatools/sunshine/junit4/JunitSuite.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.junit4; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import org.tatools.sunshine.core.*; 6 | 7 | /** 8 | * The {@link JunitSuite} class represents a JUnit 4 suite prepared from the Java classes. 9 | * 10 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 11 | * @version $Id: 2c416b810dafb2db3491b41b4988e73a70b2baf0 $ 12 | * @since 0.1 13 | */ 14 | public class JunitSuite implements Suite[]> { 15 | 16 | private final SunshineSuite suite; 17 | 18 | /** 19 | * Construct the new instance with the specified tests filter. All tests will be loaded from the 20 | * classpath. 21 | * 22 | * @param filter the filter to be used to select desired tests 23 | * @see #JunitSuite(FileSystem, Condition) 24 | * @since 0.2 25 | */ 26 | public JunitSuite(Condition filter) { 27 | this(new FileSystemOfClasspathClasses(), filter); 28 | } 29 | 30 | /** 31 | * Construct the new instance with the specified file system and tests filter. All filtered 32 | * tests will be printed to {@link System#out}. 33 | * 34 | * @param fileSystem the place with the tests 35 | * @param filter the filter to be used to select desired tests 36 | * @since 0.1 37 | */ 38 | public JunitSuite(FileSystem fileSystem, Condition filter) { 39 | this( 40 | new SunshineSuitePrintable( 41 | new SunshineSuiteFilterable(new SuiteFromFileSystem(fileSystem), filter))); 42 | } 43 | 44 | /** 45 | * Construct the new instance with the specified suite. 46 | * 47 | * @param classesAsSuite the suite with the tests 48 | * @since 0.1 49 | */ 50 | public JunitSuite(SunshineSuite classesAsSuite) { 51 | this.suite = classesAsSuite; 52 | } 53 | 54 | @Override 55 | public final Class[] tests() throws SuiteException { 56 | List> tests = new ArrayList<>(); 57 | for (SunshineTest test : this.suite.tests()) { 58 | try { 59 | tests.add(test.object()); 60 | } catch (TestException e) { 61 | throw new SuiteException(e); 62 | } 63 | } 64 | return tests.toArray(new Class[] {}); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /sunshine-junit4/src/main/java/org/tatools/sunshine/junit4/Sunshine.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.junit4; 2 | 3 | import org.tatools.sunshine.core.RegexCondition; 4 | import org.tatools.sunshine.core.Sun; 5 | import org.tatools.sunshine.core.VerboseRegex; 6 | 7 | /** 8 | * The {@link Sunshine} class is a main class to run Junit 4 tests. 9 | * 10 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 11 | * @version $Id: 9c0779a42c86336ad9edcaf26f5c15acea4f2506 $ 12 | * @since 0.1 13 | */ 14 | public final class Sunshine { 15 | 16 | public static void main(String[] args) { 17 | new Sun(new Junit4Kernel(new JunitSuite(new VerboseRegex(new RegexCondition())))).shine(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /sunshine-junit4/src/main/java/org/tatools/sunshine/junit4/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The main package of the integration with JUnit4. 3 | * 4 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 5 | * @version $Id: 4627a7014cb52d5209ec7df7be0bcd48cc738a99 $ 6 | * @since 0.2 7 | */ 8 | package org.tatools.sunshine.junit4; 9 | -------------------------------------------------------------------------------- /sunshine-junit4/src/test/java/org/tatools/sunshine/junit4/Junit4KernelTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.junit4; 2 | 3 | import org.hamcrest.MatcherAssert; 4 | import org.hamcrest.Matchers; 5 | import org.junit.Test; 6 | import org.junit.runner.Description; 7 | import org.junit.runner.notification.RunListener; 8 | import org.tatools.sunshine.core.KernelException; 9 | import org.tatools.sunshine.core.SuiteException; 10 | 11 | /** 12 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 13 | * @version $Id: ea58449403a9a536f3cced3be54605aea0f55b13 $ 14 | * @since 0.2 15 | */ 16 | public class Junit4KernelTest { 17 | 18 | @Test 19 | public void run() throws KernelException { 20 | MatcherAssert.assertThat( 21 | new Junit4Kernel(() -> new Class[] {}).status().code(), 22 | Matchers.equalTo((short) 0)); 23 | } 24 | 25 | @Test(expected = KernelException.class) 26 | public void runWithFail() throws KernelException { 27 | new Junit4Kernel( 28 | () -> { 29 | throw new SuiteException("Fail"); 30 | }) 31 | .status(); 32 | } 33 | 34 | @Test 35 | public void with() throws KernelException { 36 | final Listener l1 = new Listener(); 37 | final Listener l2 = new Listener(); 38 | new Junit4Kernel(() -> new Class[] {}).with(l1).with(l2).status(); 39 | MatcherAssert.assertThat(l1, Matchers.not(Matchers.equalTo(l2))); 40 | } 41 | 42 | private static final class Listener extends RunListener { 43 | private int status = 0; 44 | 45 | @Override 46 | public void testRunStarted(Description description) { 47 | status++; 48 | } 49 | 50 | @Override 51 | public boolean equals(Object o) { 52 | if (this == o) return true; 53 | if (o == null || getClass() != o.getClass()) return false; 54 | 55 | Junit4KernelTest.Listener listener = (Junit4KernelTest.Listener) o; 56 | 57 | return this.status == listener.status; 58 | } 59 | 60 | @Override 61 | public int hashCode() { 62 | return this.status; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /sunshine-junit4/src/test/java/org/tatools/sunshine/junit4/JunitStatusTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.junit4; 2 | 3 | import org.hamcrest.MatcherAssert; 4 | import org.hamcrest.Matchers; 5 | import org.junit.Test; 6 | import org.junit.runner.Result; 7 | 8 | /** 9 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 10 | * @version $Id: 21e6cf4ed8d7697e3fe6c4abc1065e076ce6c867 $ 11 | * @since 0.2 12 | */ 13 | public class JunitStatusTest { 14 | @Test 15 | public void codeIfPassed() { 16 | MatcherAssert.assertThat( 17 | new JunitStatus(new FakeResult(true, 0, 0, 0)).code(), Matchers.is((short) 0)); 18 | } 19 | 20 | @Test 21 | public void codeIfFailed() { 22 | MatcherAssert.assertThat( 23 | new JunitStatus(new FakeResult(false, 0, 0, 0)).code(), Matchers.is((short) 1)); 24 | } 25 | 26 | @Test 27 | public void runCount() { 28 | MatcherAssert.assertThat( 29 | new JunitStatus(new FakeResult(false, 3, 0, 0)).runCount(), Matchers.is(3)); 30 | } 31 | 32 | @Test 33 | public void failureCount() { 34 | MatcherAssert.assertThat( 35 | new JunitStatus(new FakeResult(false, 0, 2, 0)).failureCount(), Matchers.is(2)); 36 | } 37 | 38 | @Test 39 | public void ignoreCount() { 40 | MatcherAssert.assertThat( 41 | new JunitStatus(new FakeResult(false, 0, 0, 5)).ignoreCount(), Matchers.is(5)); 42 | } 43 | 44 | private final class FakeResult extends Result { 45 | private static final long serialVersionUID = -7061965103897931256L; 46 | private final boolean wasSuccessful; 47 | private final int runCount; 48 | private final int failureCount; 49 | private final int ignoreCount; 50 | 51 | FakeResult(boolean successful, int total, int failed, int ignored) { 52 | this.wasSuccessful = successful; 53 | this.runCount = total; 54 | this.failureCount = failed; 55 | this.ignoreCount = ignored; 56 | } 57 | 58 | @Override 59 | public int getRunCount() { 60 | return this.runCount; 61 | } 62 | 63 | @Override 64 | public int getFailureCount() { 65 | return this.failureCount; 66 | } 67 | 68 | @Override 69 | public int getIgnoreCount() { 70 | return this.ignoreCount; 71 | } 72 | 73 | @Override 74 | public boolean wasSuccessful() { 75 | return this.wasSuccessful; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /sunshine-junit4/src/test/java/org/tatools/sunshine/junit4/JunitSuiteTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.junit4; 2 | 3 | import java.util.Collections; 4 | import org.hamcrest.MatcherAssert; 5 | import org.hamcrest.Matchers; 6 | import org.junit.Test; 7 | import org.tatools.sunshine.core.Condition; 8 | import org.tatools.sunshine.core.FileSystem; 9 | import org.tatools.sunshine.core.SuiteException; 10 | 11 | /** 12 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 13 | * @version $Id: 0820ce02a546b1e384d53933ab588f2d137d96b8 $ 14 | * @since 0.2 15 | */ 16 | public class JunitSuiteTest { 17 | @Test 18 | public void testDefaultSuite() throws SuiteException { 19 | MatcherAssert.assertThat( 20 | new JunitSuite(() -> Collections.emptyList()).tests(), Matchers.arrayWithSize(0)); 21 | } 22 | 23 | @Test 24 | public void testDefaultFileSystemAndTestsFilter() throws SuiteException { 25 | MatcherAssert.assertThat( 26 | new JunitSuite(new FileSystem.Fake(), new Condition.Fake(false)).tests(), 27 | Matchers.arrayWithSize(0)); 28 | } 29 | 30 | @Test 31 | public void testDefaultTestsFilter() throws SuiteException { 32 | MatcherAssert.assertThat( 33 | new JunitSuite(new Condition.Fake(false)).tests(), Matchers.arrayWithSize(0)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /sunshine-junit5-integration-tests/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | } 5 | dependencies { 6 | classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.3' 7 | } 8 | } 9 | 10 | apply plugin: 'com.github.johnrengelman.shadow' 11 | 12 | dependencies { 13 | jar { 14 | manifest { 15 | attributes 'Main-Class': 'org.tatools.sunshine.junit5.Sunshine' 16 | attributes "Class-Path": configurations.runtime.collect { 17 | "deps/" + it.getName() 18 | }.join(' ') 19 | } 20 | } 21 | } 22 | 23 | task storeDependencies(type: Copy) { 24 | into "$buildDir/libs/deps" 25 | from configurations.runtime 26 | } 27 | 28 | build.dependsOn(storeDependencies) 29 | 30 | task runIntegrationTests { Task task -> 31 | doLast { 32 | task.project.exec { 33 | executable "sh" 34 | args "-c", "cd build/libs/ && java -jar ${project.name}-${version}.jar " + 35 | "| grep \"Total tests run: 1, Failures: 0, Skips: 0\"" 36 | } 37 | task.project.exec { 38 | executable "sh" 39 | args "-c", "cd build/libs/ && " + 40 | "java -Dtests-regex=\"(org.tatools.junit5tests)(.+)?\" -jar ${project.name}-${version}-all.jar " + 41 | "| grep \"Total tests run: 1, Failures: 0, Skips: 0\"" 42 | } 43 | } 44 | } 45 | runIntegrationTests.dependsOn(build) 46 | runIntegrationTests.dependsOn(shadowJar) 47 | 48 | task ready(dependsOn: runIntegrationTests) { 49 | doLast { 50 | println("Sunshine JUnit 5 integration testing is completed.") 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /sunshine-junit5-integration-tests/src/main/java/org/tatools/junit5tests/PassedTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.junit5tests; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | /** 6 | * @author Dmytro Serdiuk 7 | * @version $Id: 32c9a51bfb72dd7c4dfb8636e2fde2048e244717 $ 8 | */ 9 | public class PassedTest { 10 | @Test 11 | public void test() {} 12 | } 13 | -------------------------------------------------------------------------------- /sunshine-junit5-integration-tests/src/main/java/org/tatools/junit5tests/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The package is used to hold the classes for integration testing of the sunshine-junit5. 3 | * 4 | * @author Dmytro Serdiuk 5 | * @version $Id: d4bdf5ef51ba327f72e0b94dc8f0dd7b53518c15 $ 6 | */ 7 | package org.tatools.junit4tests; 8 | -------------------------------------------------------------------------------- /sunshine-junit5/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compileOnly 'org.projectlombok:lombok:1.16.14' 3 | annotationProcessor 'org.projectlombok:lombok:1.16.14' 4 | testCompileOnly 'org.projectlombok:lombok:1.16.14' 5 | testAnnotationProcessor 'org.projectlombok:lombok:1.16.14' 6 | compile 'org.junit.jupiter:junit-jupiter:5.5.2' 7 | compile 'org.junit.platform:junit-platform-launcher:1.5.2' 8 | testCompile 'org.hamcrest:hamcrest-all:1.3' 9 | } 10 | 11 | task ready(dependsOn: check) { 12 | doLast { 13 | println("Unit testing of Sunshine JUnit 5 is completed.") 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /sunshine-junit5/gradle.properties: -------------------------------------------------------------------------------- 1 | NAME="Sunshine JUnit 5 adapter" 2 | DESCRIPTION="The package is Sunshine's adapter for JUnit 5 tests runner." 3 | -------------------------------------------------------------------------------- /sunshine-junit5/src/main/java/org/tatools/sunshine/junit5/Junit5Kernel.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.junit5; 2 | 3 | import org.junit.platform.engine.DiscoverySelector; 4 | import org.junit.platform.engine.discovery.DiscoverySelectors; 5 | import org.junit.platform.launcher.Launcher; 6 | import org.junit.platform.launcher.TestExecutionListener; 7 | import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; 8 | import org.junit.platform.launcher.core.LauncherFactory; 9 | import org.junit.platform.launcher.listeners.SummaryGeneratingListener; 10 | import org.tatools.sunshine.core.*; 11 | 12 | /** 13 | * The class provides a {@link Kernel} implementation of JUnit 5 runner. 14 | * 15 | * @author Dmytro Serdiuk 16 | * @version $Id: cacdbc46c57af63765444ae0306578c5a6b0ac89 $ 17 | */ 18 | public class Junit5Kernel implements Kernel { 19 | 20 | private final Launcher launcher; 21 | private final SunshineSuite tests; 22 | private final SummaryGeneratingListener reporter; 23 | 24 | /** 25 | * Initializes a newly created {@link Junit5Kernel} object so that it represents an JUnit 4 26 | * runner. 27 | * 28 | * @param sunshineSuite the suite with desired tests 29 | */ 30 | public Junit5Kernel(SunshineSuite sunshineSuite) { 31 | this(LauncherFactory.create(), sunshineSuite); 32 | } 33 | 34 | /** 35 | * Initializes a newly created {@link Junit5Kernel} object so that it represents an JUnit 4 36 | * runner. 37 | * 38 | * @param launcher the launcher for a given test suite 39 | * @param sunshineSuite the suite with desired tests 40 | */ 41 | private Junit5Kernel(Launcher launcher, SunshineSuite sunshineSuite) { 42 | this.tests = sunshineSuite; 43 | this.launcher = launcher; 44 | this.reporter = new SummaryGeneratingListener(); 45 | this.launcher.registerTestExecutionListeners(this.reporter); 46 | } 47 | 48 | /** 49 | * Returns a status of JUnite 5 tests execution. 50 | * 51 | * @return the status for the current execution 52 | * @throws KernelException if any error occurs during JUnit tests execution 53 | */ 54 | @Override 55 | public final Status status() throws KernelException { 56 | try { 57 | launcher.execute( 58 | LauncherDiscoveryRequestBuilder.request() 59 | .selectors( 60 | tests.tests().stream() 61 | .map( 62 | sunshineTest -> 63 | DiscoverySelectors.selectClass( 64 | sunshineTest.toString())) 65 | .toArray(DiscoverySelector[]::new)) 66 | .build()); 67 | return new Junit5Status(this.reporter.getSummary()); 68 | } catch (SuiteException e) { 69 | throw new KernelException("Some problem occurs in the Junit5Kernel", e); 70 | } 71 | } 72 | 73 | /** 74 | * Returns a new instance of the JUnit 5 kernel with provided listeners based on the current 75 | * instance configuration. 76 | * 77 | * @param testExecutionListeners at least one desired listener 78 | * @return the new instance of the JUnit 5 kernel 79 | */ 80 | @Override 81 | public final Kernel with( 82 | TestExecutionListener... testExecutionListeners) { 83 | final Launcher fork = LauncherFactory.create(); 84 | fork.registerTestExecutionListeners(testExecutionListeners); 85 | return new Junit5Kernel(fork, this.tests); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /sunshine-junit5/src/main/java/org/tatools/sunshine/junit5/Junit5Status.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.junit5; 2 | 3 | import org.junit.platform.launcher.listeners.SummaryGeneratingListener; 4 | import org.junit.platform.launcher.listeners.TestExecutionSummary; 5 | import org.tatools.sunshine.core.Status; 6 | 7 | /** 8 | * The class provides an implementation of the {@link Status} for JUnit 5 execution. 9 | * 10 | * @author Dmytro Serdiuk 11 | * @version $Id: 80a6656bfe76025219dec8cbcca1f2ec895ac22c $ 12 | */ 13 | public class Junit5Status implements Status { 14 | private final TestExecutionSummary summary; 15 | private final short passed = 0; 16 | private final short failed = 1; 17 | 18 | /** 19 | * Initializes a newly created instance to represent a status of JUnit 5 execution. 20 | * 21 | * @param testExecutionSummary the report provided by {@link SummaryGeneratingListener} 22 | */ 23 | public Junit5Status(TestExecutionSummary testExecutionSummary) { 24 | this.summary = testExecutionSummary; 25 | } 26 | 27 | @Override 28 | public final short code() { 29 | return this.summary.getTotalFailureCount() == 0 ? this.passed : this.failed; 30 | } 31 | 32 | @Override 33 | public final int runCount() { 34 | return Math.toIntExact(this.summary.getTestsFoundCount()); 35 | } 36 | 37 | @Override 38 | public final int failureCount() { 39 | return Math.toIntExact(this.summary.getTestsFailedCount()); 40 | } 41 | 42 | @Override 43 | public final int ignoreCount() { 44 | return Math.toIntExact(this.summary.getTestsSkippedCount()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /sunshine-junit5/src/main/java/org/tatools/sunshine/junit5/Sunshine.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.junit5; 2 | 3 | import org.tatools.sunshine.core.*; 4 | 5 | /** 6 | * The {@link Sunshine} class is a main class to run JUnit 5 tests. 7 | * 8 | * @author Dmytro Serdiuk 9 | * @version $Id: 621acf30d7502a211d901da3013f27170a16635d $ 10 | */ 11 | public final class Sunshine { 12 | 13 | public static void main(String[] args) { 14 | new Sun( 15 | new Junit5Kernel( 16 | new SunshineSuitePrintable( 17 | new SunshineSuiteFilterable( 18 | new SuiteFromFileSystem( 19 | new FileSystemOfClasspathClasses()), 20 | new VerboseRegex(new RegexCondition()))))) 21 | .shine(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /sunshine-junit5/src/main/java/org/tatools/sunshine/junit5/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The main package of the integration with JUnit 5. 3 | * 4 | * @author Dmytro Serdiuk 5 | * @version $Id: 6522fd8ec63b936eca51c898c27444075dcf2afb $ 6 | */ 7 | package org.tatools.sunshine.junit5; 8 | -------------------------------------------------------------------------------- /sunshine-junit5/src/test/java/org/tatools/sunshine/junit5/Junit5KernelTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.junit5; 2 | 3 | import java.util.ArrayList; 4 | import lombok.EqualsAndHashCode; 5 | import org.hamcrest.MatcherAssert; 6 | import org.hamcrest.Matchers; 7 | import org.junit.jupiter.api.Test; 8 | import org.junit.platform.engine.TestExecutionResult; 9 | import org.junit.platform.launcher.TestExecutionListener; 10 | import org.junit.platform.launcher.TestIdentifier; 11 | import org.tatools.sunshine.core.KernelException; 12 | 13 | /** 14 | * @author Dmytro Serdiuk 15 | * @version $Id: 4f516ec98ff780681a3c17d80a4ee5d5ac688cc4 $ 16 | */ 17 | public class Junit5KernelTest { 18 | 19 | @Test 20 | public void run() throws KernelException { 21 | MatcherAssert.assertThat( 22 | new Junit5Kernel(ArrayList::new).status().code(), Matchers.equalTo((short) 0)); 23 | } 24 | 25 | @Test 26 | public void with() throws KernelException { 27 | final Listener l1 = new Listener(); 28 | final Listener l2 = new Listener(); 29 | new Junit5Kernel(ArrayList::new).with(l1).with(l2).status(); 30 | MatcherAssert.assertThat(l1, Matchers.not(Matchers.equalTo(l2))); 31 | } 32 | 33 | @EqualsAndHashCode 34 | private final class Listener implements TestExecutionListener { 35 | private int call = 0; 36 | 37 | @Override 38 | public void executionFinished( 39 | TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { 40 | this.call = 1; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /sunshine-junit5/src/test/java/org/tatools/sunshine/junit5/Junit5StatusTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.junit5; 2 | 3 | import java.io.PrintWriter; 4 | import java.util.List; 5 | import org.hamcrest.MatcherAssert; 6 | import org.hamcrest.Matchers; 7 | import org.junit.jupiter.api.Test; 8 | import org.junit.platform.launcher.listeners.TestExecutionSummary; 9 | 10 | /** 11 | * @author Dmytro Serdiuk 12 | * @version $Id: 73c96c8fef0a8ff8c0060058dd59ad5dfd67c614 $ 13 | */ 14 | class Junit5StatusTest { 15 | 16 | @Test 17 | void codePassed() { 18 | MatcherAssert.assertThat( 19 | new Junit5Status(new Summary(1, 0, 0, 0)).code(), Matchers.is((short) 0)); 20 | } 21 | 22 | @Test 23 | void codeFailed() { 24 | MatcherAssert.assertThat( 25 | new Junit5Status(new Summary(1, 0, 0, 1)).code(), Matchers.is((short) 1)); 26 | } 27 | 28 | @Test 29 | void runCount() { 30 | MatcherAssert.assertThat( 31 | new Junit5Status(new Summary(5, 4, 3, 1)).runCount(), Matchers.is(5)); 32 | } 33 | 34 | @Test 35 | void failureCount() { 36 | MatcherAssert.assertThat( 37 | new Junit5Status(new Summary(5, 4, 3, 1)).failureCount(), Matchers.is(4)); 38 | } 39 | 40 | @Test 41 | void ignoreCount() { 42 | MatcherAssert.assertThat( 43 | new Junit5Status(new Summary(5, 4, 3, 1)).ignoreCount(), Matchers.is(3)); 44 | } 45 | 46 | private final class Summary implements TestExecutionSummary { 47 | private final long totalTests; 48 | private final long failedCount; 49 | private final long skippedCount; 50 | private final long totalFailedCount; 51 | 52 | public Summary( 53 | long totalTests, long failedCount, long skippedCount, long totalFailedCount) { 54 | this.totalTests = totalTests; 55 | this.failedCount = failedCount; 56 | this.skippedCount = skippedCount; 57 | this.totalFailedCount = totalFailedCount; 58 | } 59 | 60 | @Override 61 | public long getTimeStarted() { 62 | return 0; 63 | } 64 | 65 | @Override 66 | public long getTimeFinished() { 67 | return 0; 68 | } 69 | 70 | @Override 71 | public long getTotalFailureCount() { 72 | return this.totalFailedCount; 73 | } 74 | 75 | @Override 76 | public long getContainersFoundCount() { 77 | return 0; 78 | } 79 | 80 | @Override 81 | public long getContainersStartedCount() { 82 | return 0; 83 | } 84 | 85 | @Override 86 | public long getContainersSkippedCount() { 87 | return 0; 88 | } 89 | 90 | @Override 91 | public long getContainersAbortedCount() { 92 | return 0; 93 | } 94 | 95 | @Override 96 | public long getContainersSucceededCount() { 97 | return 0; 98 | } 99 | 100 | @Override 101 | public long getContainersFailedCount() { 102 | return 0; 103 | } 104 | 105 | @Override 106 | public long getTestsFoundCount() { 107 | return this.totalTests; 108 | } 109 | 110 | @Override 111 | public long getTestsStartedCount() { 112 | return 0; 113 | } 114 | 115 | @Override 116 | public long getTestsSkippedCount() { 117 | return this.skippedCount; 118 | } 119 | 120 | @Override 121 | public long getTestsAbortedCount() { 122 | return 0; 123 | } 124 | 125 | @Override 126 | public long getTestsSucceededCount() { 127 | return 0; 128 | } 129 | 130 | @Override 131 | public long getTestsFailedCount() { 132 | return this.failedCount; 133 | } 134 | 135 | @Override 136 | public void printTo(PrintWriter writer) {} 137 | 138 | @Override 139 | public void printFailuresTo(PrintWriter writer) {} 140 | 141 | @Override 142 | public List getFailures() { 143 | return null; 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /sunshine-testng-integration-tests/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | jar { 3 | manifest { 4 | attributes 'Main-Class': 'org.tatools.sunshine.testng.Sunshine' 5 | attributes "Class-Path": configurations.runtime.collect { 6 | "deps/" + it.getName() 7 | }.join(' ') 8 | } 9 | } 10 | } 11 | 12 | task storeDependencies(type: Copy) { 13 | into "$buildDir/libs/deps" 14 | from configurations.runtime 15 | } 16 | 17 | build.dependsOn(storeDependencies) 18 | 19 | task runIntegrationTests { Task task -> 20 | doLast { 21 | task.project.exec { 22 | executable "sh" 23 | args "-c", "cd build/libs/ && java -jar ${project.name}-${version}.jar " + 24 | "| grep \"Total tests run: 3\"" 25 | } 26 | task.project.exec { 27 | executable "sh" 28 | args "-c", "cd build/libs/ && java -jar ${project.name}-${version}.jar ../../src/main/resources/testng.xml " + 29 | "| grep \"Total tests run: 2\"" 30 | } 31 | task.project.exec { 32 | executable "sh" 33 | args "-c", "cd build/libs/ && java -jar ${project.name}-${version}.jar ../../src/main/resources/testng.yaml " + 34 | "| grep \"Total tests run: 2\"" 35 | } 36 | } 37 | } 38 | runIntegrationTests.dependsOn(build) 39 | 40 | task ready(dependsOn: runIntegrationTests) { 41 | doLast { 42 | println("Sunshine TestNG integration testing is completed.") 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /sunshine-testng-integration-tests/src/main/java/org/tatools/testngtests/PassedTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.testngtests; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | /** 6 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 7 | * @version $Id: 77d2ec6ce70cfa76653abc8cfb520c462ab7b5b2 $ 8 | * @since 0.1 9 | */ 10 | public class PassedTest { 11 | @Test 12 | public void test() { 13 | assert true; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /sunshine-testng-integration-tests/src/main/java/org/tatools/testngtests/TestNGXmlTest1.java: -------------------------------------------------------------------------------- 1 | package org.tatools.testngtests; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | /** 6 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 7 | * @version $Id: e114b3ec5156d44ef5a5d3d779fc7b2e0b6889e2 $ 8 | * @since 0.1 9 | */ 10 | public class TestNGXmlTest1 { 11 | @Test 12 | public void test() { 13 | assert true; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /sunshine-testng-integration-tests/src/main/java/org/tatools/testngtests/TestNGXmlTest2.java: -------------------------------------------------------------------------------- 1 | package org.tatools.testngtests; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | /** 6 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 7 | * @version $Id: 84a06e893276f27128e4e1b11d7192c9d82473b3 $ 8 | * @since 0.1 9 | */ 10 | public class TestNGXmlTest2 { 11 | @Test 12 | public void test() { 13 | assert true; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /sunshine-testng-integration-tests/src/main/java/org/tatools/testngtests/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package is used to hold the classes for integration testing of the sunshine-testng. 3 | * 4 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 5 | * @version $Id: 29b9c0717df7b41a07c15708809bb7b97d421ff1 $ 6 | * @since 0.2 7 | */ 8 | package org.tatools.testngtests; 9 | -------------------------------------------------------------------------------- /sunshine-testng-integration-tests/src/main/resources/testng.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /sunshine-testng-integration-tests/src/main/resources/testng.yaml: -------------------------------------------------------------------------------- 1 | name: "Sunshine TestNG integration tests" 2 | tests: 3 | - name: 1 4 | classes: 5 | - org.tatools.testngtests.TestNGXmlTest1 6 | 7 | - name: 2 8 | classes: 9 | - org.tatools.testngtests.TestNGXmlTest1 10 | -------------------------------------------------------------------------------- /sunshine-testng/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | compileOnly 'org.projectlombok:lombok:1.16.14' 3 | annotationProcessor 'org.projectlombok:lombok:1.16.14' 4 | compile 'org.testng:testng:6.11' 5 | testCompile 'org.hamcrest:hamcrest-all:1.3' 6 | testCompile 'junit:junit:4.11' 7 | } 8 | 9 | task ready(dependsOn: check) { 10 | doLast { 11 | println("Unit testing of Sunshine TestNG is completed.") 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /sunshine-testng/gradle.properties: -------------------------------------------------------------------------------- 1 | NAME="Sunshine TestNG adapter" 2 | DESCRIPTION="The package is Sunshine's adapter for TestNG tests runner." 3 | -------------------------------------------------------------------------------- /sunshine-testng/src/main/java/org/tatools/sunshine/testng/LoadableTestNGSuite.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.testng; 2 | 3 | import java.io.IOException; 4 | import org.tatools.sunshine.core.*; 5 | import org.testng.xml.XmlSuite; 6 | import org.testng.xml.XmlTest; 7 | 8 | /** 9 | * The {@link LoadableTestNGSuite} class represents a TestNG suite prepared from the Java classes. 10 | * The suite has to be saved as a TestNG XML file. 11 | * 12 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 13 | * @version $Id: 47df79b649b91601e48bfb8a771ad47781de5dc2 $ 14 | * @since 0.1 15 | */ 16 | @SuppressWarnings("WeakerAccess") 17 | public class LoadableTestNGSuite implements TestNGSuite { 18 | 19 | private static final String SUNSHINE_SUITE = "Sunshine suite"; 20 | private final String name; 21 | private final SunshineSuite artifacts; 22 | private final File suiteXml; 23 | 24 | /** 25 | * Construct the new instance. The {@value #SUNSHINE_SUITE} is used as a name of the suite via 26 | * wrapping of {@link #LoadableTestNGSuite(String, Condition)}. 27 | * 28 | * @param filter the filter to be used to select desired tests 29 | * @see #LoadableTestNGSuite(String, Condition) 30 | */ 31 | public LoadableTestNGSuite(Condition filter) { 32 | this(SUNSHINE_SUITE, filter); 33 | } 34 | 35 | /** 36 | * Construct the new instance. All tests will be loaded from the classpath. 37 | * 38 | * @param suiteName the name of the suite 39 | * @param filter the filter to be used to select desired tests 40 | */ 41 | public LoadableTestNGSuite(String suiteName, Condition filter) { 42 | this(suiteName, new FileSystemOfClasspathClasses(), filter); 43 | } 44 | 45 | /** 46 | * Construct the new instance. The {@value #SUNSHINE_SUITE} is used as a name of the suite via 47 | * wrapping of {@link #LoadableTestNGSuite(String, FileSystem, Condition)}. 48 | * 49 | * @param fileSystem the place with the tests 50 | * @param filter the filter to be used to select desired tests 51 | * @see #LoadableTestNGSuite(String, FileSystem, Condition) 52 | */ 53 | public LoadableTestNGSuite(FileSystem fileSystem, Condition filter) { 54 | this(SUNSHINE_SUITE, fileSystem, filter); 55 | } 56 | 57 | /** 58 | * Construct the new instance. All filtered tests will be printed to {@link System#out}. 59 | * 60 | *

The TestNG XML file will be saved to the default temporary folder. 61 | * 62 | * @param suiteName the name of the suite 63 | * @param fileSystem the place with the tests 64 | * @param filter the filter to be used to select desired tests 65 | */ 66 | public LoadableTestNGSuite(String suiteName, FileSystem fileSystem, Condition filter) { 67 | this( 68 | suiteName, 69 | new SunshineSuitePrintable( 70 | new SunshineSuiteFilterable(new SuiteFromFileSystem(fileSystem), filter))); 71 | } 72 | 73 | /** 74 | * Construct the new instance. The {@value #SUNSHINE_SUITE} is used as a name of the suite via 75 | * wrapping of {@link #LoadableTestNGSuite(String, SunshineSuite)}. 76 | * 77 | * @param suite the tests to be used 78 | * @see #LoadableTestNGSuite(String, SunshineSuite) 79 | */ 80 | public LoadableTestNGSuite(SunshineSuite suite) { 81 | this(SUNSHINE_SUITE, suite); 82 | } 83 | 84 | /** 85 | * Construct the new instance. 86 | * 87 | *

The TestNG XML file will be saved to the temporary directory named 88 | * "./sunshine-generated-suites". 89 | * 90 | * @param suiteName the name of the suite 91 | * @param suite the tests to be used 92 | */ 93 | public LoadableTestNGSuite(String suiteName, SunshineSuite suite) { 94 | this( 95 | suiteName, 96 | suite, 97 | new DirectoryWithAutomaticCreation( 98 | new DirectoryWithAutomaticDeletion( 99 | new DirectorySafe("./sunshine-generated-suites")))); 100 | } 101 | 102 | /** 103 | * Construct the new instance. The {@value #SUNSHINE_SUITE} is used as a name of the suite via 104 | * wrapping of {@link #LoadableTestNGSuite(String, FileSystem, String, Condition)}. 105 | * 106 | * @param fileSystem the place with the tests 107 | * @param xmlSuiteDirectory the place to store suite file 108 | * @param filter the filter to be used to select desired tests 109 | * @see #LoadableTestNGSuite(String, FileSystem, String, Condition) 110 | */ 111 | public LoadableTestNGSuite(FileSystem fileSystem, String xmlSuiteDirectory, Condition filter) { 112 | this(SUNSHINE_SUITE, fileSystem, xmlSuiteDirectory, filter); 113 | } 114 | 115 | /** 116 | * Construct the new instance. If suite's directory ({@code xmlSuiteDirectory}) doesn't exist, 117 | * it will be created automatically. 118 | * 119 | * @param suiteName the name of the suite 120 | * @param fileSystem the place with the tests 121 | * @param xmlSuiteDirectory the place to store suite file 122 | * @param filter the filter to be used to select desired tests 123 | */ 124 | public LoadableTestNGSuite( 125 | String suiteName, FileSystem fileSystem, String xmlSuiteDirectory, Condition filter) { 126 | this( 127 | suiteName, 128 | fileSystem, 129 | new DirectoryWithAutomaticCreation( 130 | new DirectorySafe(new DirectoryBase(xmlSuiteDirectory))), 131 | filter); 132 | } 133 | 134 | /** 135 | * Construct the new instance. The {@value #SUNSHINE_SUITE} is used as a name of the suite via 136 | * wrapping of {@link #LoadableTestNGSuite(String, FileSystem, Directory, Condition)}. 137 | * 138 | * @param fileSystem the place with the tests 139 | * @param xmlSuiteDirectory the place to store suite file 140 | * @param filter the filter to be used to select desired tests 141 | * @see #LoadableTestNGSuite(String, FileSystem, Directory, Condition) 142 | */ 143 | public LoadableTestNGSuite( 144 | FileSystem fileSystem, Directory xmlSuiteDirectory, Condition filter) { 145 | this(SUNSHINE_SUITE, fileSystem, xmlSuiteDirectory, filter); 146 | } 147 | 148 | /** 149 | * Construct the new instance. All filtered tests will be printed to {@link System#out}. 150 | * 151 | * @param suiteName the name of the suite 152 | * @param fileSystem the place with the tests 153 | * @param xmlSuiteDirectory the place to store suite file 154 | * @param filter the filter to be used to select desired tests 155 | */ 156 | public LoadableTestNGSuite( 157 | String suiteName, 158 | FileSystem fileSystem, 159 | Directory xmlSuiteDirectory, 160 | Condition filter) { 161 | this( 162 | suiteName, 163 | new SunshineSuitePrintable( 164 | new SunshineSuiteFilterable(new SuiteFromFileSystem(fileSystem), filter)), 165 | xmlSuiteDirectory); 166 | } 167 | 168 | /** 169 | * Construct the new instance. The {@value #SUNSHINE_SUITE} is used as a name of the suite via 170 | * wrapping of {@link #LoadableTestNGSuite(String, SunshineSuite, Directory)}. 171 | * 172 | * @param suite the tests to be used 173 | * @param xmlSuiteDirectory the directory to store suite file 174 | * @see #LoadableTestNGSuite(String, SunshineSuite, Directory) 175 | */ 176 | public LoadableTestNGSuite(SunshineSuite suite, Directory xmlSuiteDirectory) { 177 | this(SUNSHINE_SUITE, suite, xmlSuiteDirectory); 178 | } 179 | 180 | /** 181 | * Construct the new instance. "sunshine-suite.xml" is used as a name for XML suite file. 182 | * 183 | * @param suiteName the name of the suite 184 | * @param suite the tests to be used 185 | * @param xmlSuiteDirectory the directory to store suite file 186 | */ 187 | public LoadableTestNGSuite(String suiteName, SunshineSuite suite, Directory xmlSuiteDirectory) { 188 | this(suiteName, suite, new FileBase(xmlSuiteDirectory, "sunshine-suite.xml")); 189 | } 190 | 191 | /** 192 | * Construct the new instance. 193 | * 194 | * @param suiteName the name of the suite 195 | * @param suite the suite 196 | * @param xmlFileName the name of TestNG XML file 197 | */ 198 | public LoadableTestNGSuite(String suiteName, SunshineSuite suite, File xmlFileName) { 199 | this.name = suiteName; 200 | this.artifacts = suite; 201 | this.suiteXml = xmlFileName; 202 | } 203 | 204 | @Override 205 | public final File tests() throws SuiteException { 206 | XmlSuite xmlSuite = new XmlSuite(); 207 | xmlSuite.setName(this.name); 208 | try { 209 | for (SunshineTest sunshineTest : this.artifacts.tests()) { 210 | XmlTest test = new TestNGTest(sunshineTest).object(); 211 | test.setSuite(xmlSuite); 212 | xmlSuite.addTest(test); 213 | } 214 | this.suiteXml.write(xmlSuite.toXml()); 215 | return this.suiteXml; 216 | } catch (TestException | IOException e) { 217 | throw new SuiteException(e); 218 | } 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /sunshine-testng/src/main/java/org/tatools/sunshine/testng/PreparedTestNGSuite.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.testng; 2 | 3 | import org.tatools.sunshine.core.FileSystemPath; 4 | import org.tatools.sunshine.core.FileSystemPathBase; 5 | 6 | /** 7 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 8 | * @version $Id: ee0f57f955894d314531e657052b3386f3199191 $ 9 | * @since 0.1 10 | */ 11 | public class PreparedTestNGSuite implements TestNGSuite { 12 | 13 | private final FileSystemPath fileSystemPath; 14 | 15 | public PreparedTestNGSuite(String path) { 16 | this(new FileSystemPathBase(path)); 17 | } 18 | 19 | public PreparedTestNGSuite(FileSystemPath fileSystemPath) { 20 | this.fileSystemPath = fileSystemPath; 21 | } 22 | 23 | @Override 24 | public final FileSystemPath tests() { 25 | return fileSystemPath; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sunshine-testng/src/main/java/org/tatools/sunshine/testng/Sunshine.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.testng; 2 | 3 | import org.tatools.sunshine.core.RegexCondition; 4 | import org.tatools.sunshine.core.Sun; 5 | import org.tatools.sunshine.core.VerboseRegex; 6 | 7 | /** 8 | * The {@link Sunshine} class is a main class to run TestNG tests. 9 | * 10 | *

If no arguments will be provided, then Sunshine will try to find TestNG tests in the 11 | * CLASSPATH. 12 | * 13 | *

If an argument will be provided, then Sunshine will run TestNG with given argument. The 14 | * argument is a path to TestNG configuration file (XML or YAML). 15 | * 16 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 17 | * @version $Id: f42195c1eb94ad36cc677cd7cef6f45d7f57d27f $ 18 | * @since 0.1 19 | */ 20 | public final class Sunshine { 21 | 22 | public static void main(String[] args) { 23 | if (args != null && args.length > 0) { 24 | new Sun(new TestNGKernel(new PreparedTestNGSuite(args[0]))).shine(); 25 | } else { 26 | new Sun( 27 | new TestNGKernel( 28 | new LoadableTestNGSuite( 29 | new VerboseRegex(new RegexCondition())))) 30 | .shine(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sunshine-testng/src/main/java/org/tatools/sunshine/testng/SunshineTestNG.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.testng; 2 | 3 | import java.util.List; 4 | import org.testng.ISuite; 5 | import org.testng.TestNG; 6 | 7 | /** 8 | * The {@link SunshineTestNG} class is the default configuration of TestNG defined for Sunshine. 9 | * 10 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 11 | * @version $Id: 2851c6ce210dedb1925bd37fa54c6180f7bf5e93 $ 12 | * @since 0.2 13 | */ 14 | final class SunshineTestNG extends TestNG { 15 | 16 | private final List database; 17 | 18 | /** 19 | * Constructs the instance of TestNG without default listeners and with 0 verbose mode (no 20 | * logs). All executed suites will be saved to a given list. 21 | * 22 | * @param suitesHolder the list to store suites 23 | */ 24 | SunshineTestNG(List suitesHolder) { 25 | super(false); 26 | this.database = suitesHolder; 27 | this.setVerbose(0); 28 | } 29 | 30 | @Override 31 | protected List runSuites() { 32 | final List suites = super.runSuites(); 33 | this.database.addAll(suites); 34 | return suites; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sunshine-testng/src/main/java/org/tatools/sunshine/testng/TestNGKernel.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.testng; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Collections; 6 | import java.util.List; 7 | import org.tatools.sunshine.core.*; 8 | import org.testng.ISuite; 9 | import org.testng.ITestNGListener; 10 | import org.testng.TestNG; 11 | 12 | /** 13 | * The {@link TestNGKernel} class allows to run TestNG for given {@link FileSystem}. 14 | * 15 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 16 | * @version $Id: fa1d2ec3b5780809a9fd8c3af43b295460f7308b $ 17 | * @since 0.2 18 | */ 19 | public class TestNGKernel implements Kernel { 20 | 21 | private final TestNG engine; 22 | private final TestNGSuite suite; 23 | private final List suites; 24 | 25 | /** 26 | * Initializes a newly created {@link TestNGKernel} object so that it represents an TestNG 27 | * runner. 28 | * 29 | * @param tests an instance of a {@link TestNGSuite} where need to find tests 30 | */ 31 | public TestNGKernel(TestNGSuite tests) { 32 | this.suites = new ArrayList<>(); 33 | this.engine = new SunshineTestNG(this.suites); 34 | this.suite = tests; 35 | } 36 | 37 | @Override 38 | public final Status status() throws KernelException { 39 | try { 40 | this.suites.clear(); 41 | this.engine.setTestSuites( 42 | Collections.singletonList(this.suite.tests().path().toString())); 43 | this.engine.run(); 44 | return new TestNGStatus(engine.getStatus(), this.suites); 45 | } catch (SuiteException e) { 46 | throw new KernelException("Some problem occurs in the TestNGKernel", e); 47 | } 48 | } 49 | 50 | /** 51 | * Constructs new {@link TestNGKernel} object with wanted listeners. 52 | * 53 | * @param listeners an instance (or instances) of engine's listeners 54 | * @return an instance of {@link TestNGKernel} 55 | */ 56 | @Override 57 | public final TestNGKernel with(ITestNGListener... listeners) { 58 | final TestNGKernel kernel = new TestNGKernel(this.suite); 59 | Arrays.stream(listeners).forEach(kernel.engine::addListener); 60 | return kernel; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /sunshine-testng/src/main/java/org/tatools/sunshine/testng/TestNGStatus.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.testng; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import org.tatools.sunshine.core.Status; 6 | import org.testng.ISuite; 7 | import org.testng.ISuiteResult; 8 | import org.testng.ITestContext; 9 | 10 | /** 11 | * The class provides an implementation of the {@link Status} of TestNG execution. 12 | * 13 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 14 | * @version $Id: 1c15a0f605a9710151649a6a0f92e21aa56928b8 $ 15 | * @since 0.2 16 | */ 17 | public class TestNGStatus implements Status { 18 | 19 | private final short exit_code; 20 | private final List reports; 21 | private final List counts; 22 | 23 | public TestNGStatus(int status, List suites) { 24 | this.exit_code = (short) status; 25 | this.reports = suites; 26 | this.counts = new ArrayList<>(3); 27 | } 28 | 29 | @Override 30 | public final short code() { 31 | return this.exit_code; 32 | } 33 | 34 | @Override 35 | public final int runCount() { 36 | this.calculate(); 37 | return this.counts.get(0).intValue(); 38 | } 39 | 40 | @Override 41 | public final int failureCount() { 42 | this.calculate(); 43 | return this.counts.get(1).intValue(); 44 | } 45 | 46 | @Override 47 | public final int ignoreCount() { 48 | this.calculate(); 49 | return this.counts.get(2).intValue(); 50 | } 51 | 52 | private void calculate() { 53 | if (!this.counts.isEmpty()) return; 54 | int passed = 0; 55 | int failed = 0; 56 | int skipped = 0; 57 | 58 | for (ISuite suite : this.reports) { 59 | for (ISuiteResult result : suite.getResults().values()) { 60 | final ITestContext testContext = result.getTestContext(); 61 | passed += testContext.getPassedTests().size(); 62 | failed += testContext.getFailedTests().size(); 63 | skipped += testContext.getSkippedTests().size(); 64 | } 65 | } 66 | this.counts.add(0, passed + failed + skipped); 67 | this.counts.add(1, failed); 68 | this.counts.add(2, skipped); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /sunshine-testng/src/main/java/org/tatools/sunshine/testng/TestNGSuite.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.testng; 2 | 3 | import org.tatools.sunshine.core.FileSystemPath; 4 | import org.tatools.sunshine.core.Suite; 5 | import org.tatools.sunshine.core.SuiteException; 6 | 7 | /** 8 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 9 | * @version $Id: 1f11bb02c20eeab0655fa86a5caa2e4f743d1b7c $ 10 | * @since 0.1 11 | */ 12 | public interface TestNGSuite extends Suite { 13 | /** 14 | * Return a TestNG tests file. 15 | * 16 | * @return an instance of {@link FileSystemPath}. 17 | * @throws SuiteException if some error occurs 18 | */ 19 | @Override 20 | FileSystemPath tests() throws SuiteException; 21 | } 22 | -------------------------------------------------------------------------------- /sunshine-testng/src/main/java/org/tatools/sunshine/testng/TestNGTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.testng; 2 | 3 | import java.util.Collections; 4 | import org.tatools.sunshine.core.*; 5 | import org.testng.xml.XmlClass; 6 | import org.testng.xml.XmlTest; 7 | 8 | /** 9 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 10 | * @version $Id: 9d3e448a3431caddaa4e555867e35c7ae1ab25a3 $ 11 | * @since 0.1 12 | */ 13 | final class TestNGTest implements Test { 14 | private final SunshineTest test; 15 | 16 | TestNGTest(SunshineTest test) { 17 | this.test = test; 18 | } 19 | 20 | TestNGTest(String clazz) { 21 | this(new TestFromFile(clazz)); 22 | } 23 | 24 | @Override 25 | public XmlTest object() throws TestException { 26 | XmlTest xmlTest = new XmlTest(); 27 | xmlTest.setName(test.toString()); 28 | xmlTest.setXmlClasses(Collections.singletonList(new XmlClass(test.object(), false))); 29 | return xmlTest; 30 | } 31 | 32 | @Override 33 | public boolean match(Condition condition) { 34 | throw new UnsupportedOperationException( 35 | String.format( 36 | "%s is not able to handle %s condition", 37 | this.getClass().getName(), condition.getClass().getName())); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /sunshine-testng/src/main/java/org/tatools/sunshine/testng/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The main package of the integration with TestNG. 3 | * 4 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 5 | * @version $Id: 77f28157f65ded77cfd928baf68093577ac0e81c $ 6 | * @since 0.2 7 | */ 8 | package org.tatools.sunshine.testng; 9 | -------------------------------------------------------------------------------- /sunshine-testng/src/test/java/org/tatools/sunshine/testng/LoadableTestNGSuiteTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.testng; 2 | 3 | import org.hamcrest.CustomMatcher; 4 | import org.hamcrest.MatcherAssert; 5 | import org.junit.Rule; 6 | import org.junit.Test; 7 | import org.junit.rules.TemporaryFolder; 8 | import org.tatools.sunshine.core.*; 9 | 10 | /** 11 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 12 | * @version $Id: ef70c92c6fe60666e3182d265ffbff97e7aad0d9 $ 13 | * @since 0.2 14 | */ 15 | public class LoadableTestNGSuiteTest { 16 | 17 | @Rule public TemporaryFolder testFolder = new TemporaryFolder(); 18 | 19 | @Test 20 | public void testAutomaticSuiteDirectoryCreation() throws SuiteException { 21 | MatcherAssert.assertThat( 22 | new LoadableTestNGSuite( 23 | new FileSystem.Fake(), 24 | this.testFolder.getRoot().getAbsolutePath() + "/custom", 25 | new Condition.Fake(true)) 26 | .tests(), 27 | new SuiteFileMatcher()); 28 | } 29 | 30 | @Test 31 | public void testDefaultSuiteDirectoryCreation() throws SuiteException { 32 | MatcherAssert.assertThat( 33 | new LoadableTestNGSuite(new SunshineSuite.Fake()).tests(), new SuiteFileMatcher()); 34 | } 35 | 36 | @Test 37 | public void testFileSystemFilteringWithDefaultSuiteFolder() throws SuiteException { 38 | MatcherAssert.assertThat( 39 | new LoadableTestNGSuite(new FileSystem.Fake(), new Condition.Fake(true)).tests(), 40 | new SuiteFileMatcher()); 41 | } 42 | 43 | @Test 44 | public void testDefaultTestsFiltering() throws SuiteException { 45 | MatcherAssert.assertThat( 46 | new LoadableTestNGSuite(new Condition.Fake(false)).tests(), new SuiteFileMatcher()); 47 | } 48 | 49 | private static class SuiteFileMatcher extends CustomMatcher { 50 | 51 | public SuiteFileMatcher() { 52 | super("Check existence of a suite file"); 53 | } 54 | 55 | @Override 56 | public boolean matches(Object item) { 57 | final File file = (File) item; 58 | return file.exist(); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /sunshine-testng/src/test/java/org/tatools/sunshine/testng/SunshineTestNGTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.testng; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import org.hamcrest.MatcherAssert; 6 | import org.hamcrest.Matchers; 7 | import org.junit.Test; 8 | import org.testng.ISuite; 9 | 10 | /** 11 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 12 | * @version $Id: ae6cc02e5eb4dc1351e8538109e5cc29a93f1d17 $ 13 | * @since 0.2 14 | */ 15 | public class SunshineTestNGTest { 16 | @Test 17 | public void runSuites() { 18 | final ArrayList suitesHolder = new ArrayList<>(); 19 | final SunshineTestNG sunshineTestNG = new SunshineTestNG(suitesHolder); 20 | sunshineTestNG.setTestSuites(Arrays.asList("src/test/resources/testng.xml")); 21 | sunshineTestNG.run(); 22 | MatcherAssert.assertThat(suitesHolder, Matchers.hasSize(1)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /sunshine-testng/src/test/java/org/tatools/sunshine/testng/TestNGKernelTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.testng; 2 | 3 | import org.hamcrest.MatcherAssert; 4 | import org.hamcrest.Matchers; 5 | import org.junit.Test; 6 | import org.tatools.sunshine.core.FileSystemPath; 7 | import org.tatools.sunshine.core.KernelException; 8 | import org.tatools.sunshine.core.SuiteException; 9 | import org.testng.ISuite; 10 | import org.testng.ISuiteListener; 11 | 12 | /** 13 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 14 | * @version $Id: 8d7223c49110d4b3b31b1fdf33f4d7a0a0d8244d $ 15 | * @since 0.2 16 | */ 17 | public class TestNGKernelTest { 18 | 19 | @Test 20 | public void status() throws KernelException { 21 | MatcherAssert.assertThat( 22 | new TestNGKernel(() -> new FileSystemPath.Fake("src/test/resources/testng.xml")) 23 | .status() 24 | .code(), 25 | Matchers.equalTo((short) 0)); 26 | } 27 | 28 | @Test(expected = KernelException.class) 29 | public void runWithFail() throws KernelException { 30 | new TestNGKernel( 31 | () -> { 32 | throw new SuiteException("Fail"); 33 | }) 34 | .status(); 35 | } 36 | 37 | @Test 38 | public void with() throws KernelException { 39 | final Listener l1 = new Listener(); 40 | final Listener l2 = new Listener(); 41 | new TestNGKernel(() -> new FileSystemPath.Fake("src/test/resources/testng.xml")) 42 | .with(l1) 43 | .with(l2) 44 | .status(); 45 | MatcherAssert.assertThat(l1, Matchers.not(Matchers.equalTo(l2))); 46 | } 47 | 48 | private static final class Listener implements ISuiteListener { 49 | private int status = 0; 50 | 51 | @Override 52 | public void onStart(ISuite suite) { 53 | status++; 54 | } 55 | 56 | @Override 57 | public void onFinish(ISuite suite) { 58 | status++; 59 | } 60 | 61 | @Override 62 | public boolean equals(Object o) { 63 | if (this == o) return true; 64 | if (o == null || this.getClass() != o.getClass()) return false; 65 | 66 | TestNGKernelTest.Listener listener = (TestNGKernelTest.Listener) o; 67 | 68 | return this.status == listener.status; 69 | } 70 | 71 | @Override 72 | public int hashCode() { 73 | return this.status; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /sunshine-testng/src/test/java/org/tatools/sunshine/testng/TestNGStatusTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.testng; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Collections; 6 | import java.util.List; 7 | import org.hamcrest.MatcherAssert; 8 | import org.hamcrest.Matchers; 9 | import org.junit.Test; 10 | import org.testng.ISuite; 11 | 12 | /** 13 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 14 | * @version $Id: 1c5f59662d4d8ec26f1b47ed74d2372aef73211d $ 15 | * @since 0.2 16 | */ 17 | public class TestNGStatusTest { 18 | @Test 19 | public void code() { 20 | MatcherAssert.assertThat( 21 | new TestNGStatus(4, Collections.emptyList()).code(), Matchers.equalTo((short) 4)); 22 | } 23 | 24 | @Test 25 | public void runCount() { 26 | MatcherAssert.assertThat( 27 | new TestNGStatus(0, this.suites()).runCount(), Matchers.equalTo(0)); 28 | } 29 | 30 | @Test 31 | public void failureCount() { 32 | MatcherAssert.assertThat( 33 | new TestNGStatus(0, this.suites()).failureCount(), Matchers.equalTo(0)); 34 | } 35 | 36 | @Test 37 | public void ignoreCount() { 38 | MatcherAssert.assertThat( 39 | new TestNGStatus(0, this.suites()).ignoreCount(), Matchers.equalTo(0)); 40 | } 41 | 42 | private List suites() { 43 | final ArrayList suitesHolder = new ArrayList<>(); 44 | final SunshineTestNG sunshineTestNG = new SunshineTestNG(suitesHolder); 45 | sunshineTestNG.setTestSuites(Arrays.asList("src/test/resources/testng.xml")); 46 | sunshineTestNG.run(); 47 | return suitesHolder; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /sunshine-testng/src/test/java/org/tatools/sunshine/testng/TestNGTestTest.java: -------------------------------------------------------------------------------- 1 | package org.tatools.sunshine.testng; 2 | 3 | import org.junit.Test; 4 | import org.tatools.sunshine.core.TestException; 5 | 6 | /** 7 | * @author Dmytro Serdiuk (dmytro.serdiuk@gmail.com) 8 | * @version $Id: d3c10d2a6fab523dfff1e8aecb5d835811f44849 $ 9 | * @since 0.1 10 | */ 11 | public class TestNGTestTest { 12 | 13 | @Test(expected = TestException.class) 14 | public void asClassWithGhostClass() throws TestException { 15 | new TestNGTest("org/tatools/testng/Test11.class").object(); 16 | } 17 | 18 | @Test 19 | public void withRealClass() throws TestException { 20 | new TestNGTest("org/tatools/sunshine/core/Test.class").object(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /sunshine-testng/src/test/resources/testng.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /workflows: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | formatting() { 5 | ./gradlew spotlessApply 6 | } 7 | 8 | testing() { 9 | ./gradlew clean ready 10 | } 11 | 12 | documentation-preview() { 13 | cd docs 14 | rm -rf _build 15 | make html 16 | open _build/html/index.html 17 | } 18 | 19 | main() { 20 | if [[ -n ${1} ]]; then 21 | eval "${1}" 22 | else 23 | cat < 25 | 26 | Workflows: 27 | - formatting runs the Spotless to format the code. 28 | - testing runs unit, integration, and formatting check. 29 | - documentation-preview generates HTML pages and opens in a browser. 30 | 31 | MESSAGE 32 | exit 1 33 | fi 34 | } 35 | 36 | main ${@} 37 | --------------------------------------------------------------------------------