├── .github └── workflows │ ├── RunCI.hx │ ├── RunCICoverage.hx │ ├── coverage.yml │ └── main.yml ├── .gitignore ├── .haxerc ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── build.hxml ├── checkstyle.json ├── haxe_libraries ├── hxjsonast.hxml ├── hxnodejs.hxml ├── json2object.hxml ├── simple_lcov.hxml ├── vscode.hxml └── vshaxe.hxml ├── hxformat.json ├── images ├── demo.gif └── icon.png ├── makeReleaseZip.sh ├── package-lock.json ├── package.json ├── samples ├── all-samples.code-workspace ├── buddy-instrument │ ├── .haxerc │ ├── .vscode │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ ├── haxe_libraries │ │ ├── asynctools.hxml │ │ ├── buddy.hxml │ │ ├── hxjsonast.hxml │ │ ├── hxnodejs.hxml │ │ ├── instrument.hxml │ │ ├── json2object.hxml │ │ ├── promhx.hxml │ │ ├── safety.hxml │ │ └── test-adapter.hxml │ ├── src │ │ └── Main.hx │ ├── test.hxml │ ├── testCoverage.hxml │ └── tests │ │ └── Test.hx ├── buddy │ ├── .haxerc │ ├── .vscode │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ ├── haxe_libraries │ │ ├── asynctools.hxml │ │ ├── buddy.hxml │ │ ├── hxjsonast.hxml │ │ ├── json2object.hxml │ │ ├── promhx.hxml │ │ └── test-adapter.hxml │ ├── src │ │ ├── Main.hx │ │ └── tests │ │ │ └── TestCase3.hx │ └── test.hxml ├── haxeunit │ ├── .haxerc │ ├── .vscode │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ ├── haxe_libraries │ │ ├── hx3compat.hxml │ │ ├── hxjsonast.hxml │ │ ├── json2object.hxml │ │ └── test-adapter.hxml │ ├── src │ │ ├── Main.hx │ │ └── tests │ │ │ ├── TestCase.hx │ │ │ └── TestCase3.hx │ └── test.hxml ├── hexunit │ ├── .haxerc │ ├── .vscode │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ ├── haxe_libraries │ │ ├── hexcore.hxml │ │ ├── hexlog.hxml │ │ ├── hexunit.hxml │ │ ├── hxjsonast.hxml │ │ ├── json2object.hxml │ │ ├── test-adapter.hxml │ │ ├── tink_core.hxml │ │ └── tink_macro.hxml │ ├── src │ │ ├── Main.hx │ │ └── tests │ │ │ ├── TestCase.hx │ │ │ └── TestCase3.hx │ └── test.hxml ├── munit-instrument │ ├── .haxerc │ ├── .vscode │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ ├── haxe_libraries │ │ ├── hxjsonast.hxml │ │ ├── instrument.hxml │ │ ├── json2object.hxml │ │ ├── mconsole.hxml │ │ ├── mcover.hxml │ │ ├── mlib.hxml │ │ ├── munit.hxml │ │ ├── safety.hxml │ │ └── test-adapter.hxml │ ├── src │ │ └── Main.hx │ ├── test.hxml │ ├── testCoverage.hxml │ └── tests │ │ └── Test.hx ├── munit-mcover │ ├── .haxerc │ ├── .vscode │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ ├── haxe_libraries │ │ ├── hxjsonast.hxml │ │ ├── json2object.hxml │ │ ├── mconsole.hxml │ │ ├── mcover.hxml │ │ ├── mlib.hxml │ │ ├── munit.hxml │ │ └── test-adapter.hxml │ ├── src │ │ └── Main.hx │ ├── test.hxml │ ├── testCoverage.hxml │ └── tests │ │ └── Test.hx ├── munit │ ├── .haxerc │ ├── .vscode │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ ├── haxe_libraries │ │ ├── hxjsonast.hxml │ │ ├── json2object.hxml │ │ ├── mconsole.hxml │ │ ├── mcover.hxml │ │ ├── mlib.hxml │ │ ├── munit.hxml │ │ └── test-adapter.hxml │ ├── src │ │ ├── Main.hx │ │ └── tests │ │ │ ├── TestCase.hx │ │ │ ├── TestCase3.hx │ │ │ └── TestSuite2.hx │ └── test.hxml ├── tink_unittest-instrument │ ├── .haxerc │ ├── .vscode │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ ├── haxe_libraries │ │ ├── ansi.hxml │ │ ├── hxjsonast.hxml │ │ ├── instrument.hxml │ │ ├── json2object.hxml │ │ ├── safety.hxml │ │ ├── test-adapter.hxml │ │ ├── tink_core.hxml │ │ ├── tink_macro.hxml │ │ ├── tink_priority.hxml │ │ ├── tink_streams.hxml │ │ ├── tink_syntaxhub.hxml │ │ ├── tink_testrunner.hxml │ │ └── tink_unittest.hxml │ ├── src │ │ └── Main.hx │ ├── test.hxml │ ├── testCoverage.hxml │ └── tests │ │ └── Test.hx ├── tink_unittest │ ├── .haxerc │ ├── .vscode │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ ├── haxe_libraries │ │ ├── ansi.hxml │ │ ├── hxjsonast.hxml │ │ ├── json2object.hxml │ │ ├── test-adapter.hxml │ │ ├── tink_core.hxml │ │ ├── tink_macro.hxml │ │ ├── tink_priority.hxml │ │ ├── tink_streams.hxml │ │ ├── tink_syntaxhub.hxml │ │ ├── tink_testrunner.hxml │ │ └── tink_unittest.hxml │ ├── src │ │ ├── Main.hx │ │ └── tests │ │ │ ├── TestCase.hx │ │ │ └── TestCase3.hx │ └── test.hxml ├── utest-instrument │ ├── .haxerc │ ├── .vscode │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ ├── haxe_libraries │ │ ├── hxjsonast.hxml │ │ ├── instrument.hxml │ │ ├── json2object.hxml │ │ ├── safety.hxml │ │ ├── test-adapter.hxml │ │ └── utest.hxml │ ├── src │ │ └── Main.hx │ ├── test.hxml │ ├── testCoverage.hxml │ └── tests │ │ └── Test.hx └── utest │ ├── .haxerc │ ├── .vscode │ ├── launch.json │ ├── settings.json │ └── tasks.json │ ├── haxe_libraries │ ├── hxjsonast.hxml │ ├── json2object.hxml │ ├── test-adapter.hxml │ └── utest.hxml │ ├── src │ ├── Main.hx │ └── tests │ │ ├── TestCase.hx │ │ ├── TestCase3.hx │ │ └── pack │ │ └── TestCase4.hx │ └── test.hxml ├── src └── HaxeTestController.hx └── test-adapter ├── _testadapter ├── Macro.hx ├── PatchTools.hx ├── buddy │ ├── Injector.hx │ ├── Reporter.hx │ └── Spec.hx ├── data │ ├── Data.hx │ ├── TestFilter.hx │ ├── TestPositions.hx │ └── TestResults.hx ├── haxeunit │ └── Injector.hx ├── hexunit │ ├── Injector.hx │ └── Notifier.hx ├── instrument │ └── Injector.hx ├── munit │ ├── Injector.hx │ └── ResultClient.hx ├── tink_unittest │ ├── AttributableReporter.hx │ ├── Injector.hx │ └── Reporter.hx └── utest │ ├── Injector.hx │ └── Reporter.hx ├── extraParams.hxml └── haxelib.json /.github/workflows/RunCI.hx: -------------------------------------------------------------------------------- 1 | import sys.io.File; 2 | using StringTools; 3 | 4 | class RunCI { 5 | static function main() { 6 | var success = true; 7 | function runCommand(command:String, args:Array) { 8 | Sys.println(command + " " + args.join(" ")); 9 | if (Sys.command(command, args) != 0) { 10 | success = false; 11 | } 12 | } 13 | 14 | #if haxe4 15 | runCommand("npx", ["haxe", "build.hxml"]); 16 | #end 17 | 18 | function buildSample(directory:String) { 19 | Sys.println("Building " + directory); 20 | var oldCwd = Sys.getCwd(); 21 | Sys.setCwd(directory); 22 | File.saveContent("test.hxml", File.getContent("test.hxml").replace("-x Main", "-lib test-adapter")); 23 | runCommand("npx", ["haxe", "test.hxml"]); 24 | Sys.setCwd(oldCwd); 25 | } 26 | 27 | 28 | buildSample("samples/munit"); 29 | buildSample("samples/utest"); 30 | buildSample("samples/buddy"); 31 | buildSample("samples/hexunit"); 32 | buildSample("samples/tink_unittest"); 33 | buildSample("samples/haxeunit"); 34 | 35 | Sys.exit(success ? 0 : 1); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /.github/workflows/RunCICoverage.hx: -------------------------------------------------------------------------------- 1 | import sys.io.File; 2 | using StringTools; 3 | 4 | class RunCICoverage { 5 | static function main() { 6 | var success = true; 7 | function runCommand(command:String, args:Array) { 8 | Sys.println(command + " " + args.join(" ")); 9 | if (Sys.command(command, args) != 0) { 10 | success = false; 11 | } 12 | } 13 | 14 | #if haxe4 15 | runCommand("npx", ["haxe", "build.hxml"]); 16 | #end 17 | 18 | function buildSample(directory:String) { 19 | Sys.println("Building " + directory); 20 | var oldCwd = Sys.getCwd(); 21 | Sys.setCwd(directory); 22 | File.saveContent("test.hxml", File.getContent("test.hxml").replace("-x Test", "-x Test\n-lib test-adapter")); 23 | runCommand("npx", ["haxe", "test.hxml"]); 24 | Sys.setCwd(oldCwd); 25 | } 26 | 27 | function buildSampleWithCoverage(directory:String) { 28 | Sys.println("Building " + directory + " with coverage"); 29 | var oldCwd = Sys.getCwd(); 30 | Sys.setCwd(directory); 31 | File.saveContent("testCoverage.hxml", File.getContent("testCoverage.hxml").replace("-x Test", "-x Test\n-lib test-adapter")); 32 | runCommand("npx", ["haxe", "testCoverage.hxml"]); 33 | Sys.setCwd(oldCwd); 34 | } 35 | 36 | 37 | buildSample("samples/munit-instrument"); 38 | buildSample("samples/munit-mcover"); 39 | buildSample("samples/utest-instrument"); 40 | buildSample("samples/buddy-instrument"); 41 | buildSample("samples/tink_unittest-instrument"); 42 | 43 | buildSampleWithCoverage("samples/munit-instrument"); 44 | buildSampleWithCoverage("samples/munit-mcover"); 45 | buildSampleWithCoverage("samples/utest-instrument"); 46 | buildSampleWithCoverage("samples/buddy-instrument"); 47 | buildSampleWithCoverage("samples/tink_unittest-instrument"); 48 | 49 | Sys.exit(success ? 0 : 1); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yml: -------------------------------------------------------------------------------- 1 | name: samples with coverage 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: '0 4 * * *' 8 | 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | haxe-version: [4.2.5, 4.3.6, nightly] 14 | fail-fast: false 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - run: npm install 19 | - name: install dependencies for all samples 20 | run: | 21 | for i in buddy-instrument munit-mcover munit-instrument tink_unittest-instrument utest-instrument; do ( 22 | cd ${{github.workspace}}/samples/$i; 23 | npx lix download; 24 | npx lix install haxe ${{matrix.haxe-version}}; 25 | npx lix dev test-adapter ../../test-adapter 26 | ); 27 | done 28 | working-directory: samples/buddy # this is kind of a hack (lix bug even?) 29 | - name: install git version libs for Haxe nightly 30 | if: matrix.haxe-version == 'nightly' 31 | run: | 32 | (cd ${{github.workspace}}/samples/tink_unittest; npx lix install gh:haxetink/tink_macro) 33 | - name: run samples 34 | run: npx haxe -cp .github/workflows --run RunCICoverage 35 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: samples (no coverage) 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: '0 4 * * *' 8 | 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | haxe-version: [3.4.7, 4.0.5, 4.1.5, 4.2.5, 4.3.6, nightly] 14 | fail-fast: false 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - run: npm install 19 | - name: install dependencies for all samples 20 | run: | 21 | for i in buddy haxeunit hexunit munit tink_unittest utest; do ( 22 | cd ${{github.workspace}}/samples/$i; 23 | npx lix download; 24 | npx lix install haxe ${{matrix.haxe-version}}; 25 | npx lix dev test-adapter ../../test-adapter 26 | ); 27 | done 28 | working-directory: samples/buddy # this is kind of a hack (lix bug even?) 29 | - name: install older libs for Haxe 3.4.7 30 | if: matrix.haxe-version == '3.4.7' 31 | run: | 32 | (cd ${{github.workspace}}/samples/tink_unittest; npx lix install haxelib:tink_core#1.26.0) 33 | (cd ${{github.workspace}}/samples/utest; npx lix install haxelib:utest#1.13.2) 34 | (cd ${{github.workspace}}/samples/buddy; npx lix install haxelib:utest#1.13.2) 35 | - name: install older libs for Haxe 4.0.5 36 | if: matrix.haxe-version == '4.0.5' 37 | run: | 38 | (cd ${{github.workspace}}/samples/utest; npx lix install haxelib:utest#1.13.2) 39 | (cd ${{github.workspace}}/samples/buddy; npx lix install haxelib:utest#1.13.2) 40 | - name: install git version libs for Haxe nightly 41 | if: matrix.haxe-version == 'nightly' 42 | run: | 43 | (cd ${{github.workspace}}/samples/tink_unittest; npx lix install gh:haxetink/tink_macro) 44 | - name: run samples 45 | run: npx haxe -cp .github/workflows --run RunCI 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | bin/ 3 | dump/ 4 | .unittest/ 5 | .temp/ 6 | *.n 7 | *.vsix 8 | *.zip 9 | *.lcov 10 | lcov.info -------------------------------------------------------------------------------- /.haxerc: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.3.6", 3 | "resolveLibs": "scoped" 4 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "extensionHost", 6 | "request": "launch", 7 | "name": "Extension", 8 | "runtimeExecutable": "${execPath}", 9 | "args": [ 10 | "--extensionDevelopmentPath=${workspaceFolder}" 11 | ], 12 | "outFiles": [ 13 | "${workspaceFolder}/bin" 14 | ] 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[haxe]": { 3 | "editor.formatOnSave": true, 4 | "editor.formatOnPaste": true 5 | }, 6 | "[json]": { 7 | "editor.formatOnSave": true, 8 | "editor.formatOnPaste": true 9 | }, 10 | "haxecheckstyle.sourceFolders": [ 11 | "src", 12 | "samples", 13 | "test-adapter" 14 | ] 15 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "hxml", 6 | "file": "build.hxml", 7 | "group": { 8 | "kind": "build", 9 | "isDefault": true 10 | } 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | .travis.yml 3 | RunCI.hx 4 | checkstyle.json 5 | hxformat.json 6 | package-lock.json 7 | *.hxml 8 | *.zip 9 | src/** 10 | **/*.map 11 | .vscode/** 12 | dump/** 13 | samples/** 14 | .unittest 15 | .github 16 | .haxerc 17 | haxe_libraries -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ## 3.0.1 (January 23, 2025) 4 | 5 | - removed broken badges from README 6 | 7 | ## 3.0.0 (January 23, 2025) 8 | 9 | ### Haxe Test Explorer extension 10 | 11 | - added support for new VSCode coverage view 12 | - added support for attributable coverage (via instrument lib) 13 | - added setting `haxeTestExplorer.coverageCommand` for custom coverage command 14 | - added setting `haxeTestExplorer.enableCoverageUI` - enable / disable coverage UI 15 | - added setting `haxeTestExplorer.enableAttributableCoverage` - enable / disable attributable coverage support 16 | - added setting `haxeTestExplorer.lcovPath` - path to LCOV file for coverage libraries besides instrument 17 | - added setting `haxeTestExplorer.waitForCoverage` - time in milliseconds to wait for coverage results after run 18 | - fixed progress indicator showing for all tests when running individual testcases 19 | 20 | ### test-adapter lib 21 | 22 | - added attributable coverage for utest (via instrument lib) 23 | - added attributable coverage for buddy (via instrument lib) 24 | - added attributable coverage for munit (via instrument lib) 25 | - added attributable coverage for tink_unittest (via instrument lib) 26 | - added LCOV support for coverage libs besides instrument 27 | - added `-D disable-attributable-coverage` 28 | - fixed Haxe 3.4.7 + utest compatibility 29 | 30 | ## 2.0.7 (February 12, 2024) 31 | 32 | - fixed filter support for utest 2.x 33 | - changed addMetadata to addGlobalMetadata 34 | 35 | ## 2.0.6 (December 21, 2023) 36 | 37 | - added support for upcoming utest version 2.x 38 | 39 | ## 2.0.5 (May 21, 2023) 40 | 41 | - added support for pending tests in buddy, fixes [#26](https://github.com/vshaxe/haxe-test-adapter/issues/26) 42 | 43 | ## 2.0.4 (September 5, 2022) 44 | 45 | - compiled extension with Haxe nightly 46 | 47 | ## 2.0.3 (September 5, 2022) 48 | 49 | - changed scope of configuration settings to resource level to support different settings per workspace folder in a multiroot workspace scenario 50 | 51 | ## 2.0.2 (August 24, 2022) 52 | 53 | - fixed compatibility issue with vshaxe 2.24.x 54 | 55 | ## 2.0.1 (February 17, 2022) 56 | 57 | - fixed auto collapse of test cases 58 | - fixed error positions in different file 59 | - fixed multiline diff detection 60 | 61 | ## 2.0.0 (January 27, 2022) 62 | 63 | - added support for VSCode testing API 64 | - added test execution time (in ms) for buddy, munit, hexunit and utest 65 | - dropped test explorer ui extension dependency 66 | 67 | ## 1.2.10 (October 11, 2020) 68 | 69 | - added support for nested describe calls in buddy tests 70 | 71 | ## 1.2.9 (August 15, 2020) 72 | 73 | - fixed utest injection after implementation detail changed in version 1.13.0 74 | - changed required version for utest to 1.13.0 75 | 76 | ## 1.2.8 (May 1, 2020) 77 | 78 | - fixed tink_testrunner injection to restore compatibility with version 0.8.0 79 | 80 | ## 1.2.7 (April 11, 2020) 81 | 82 | - fixed state of "Run all tests" button not being restored anymore since VSCode 1.44 83 | 84 | ## 1.2.6 (November 13, 2019) 85 | 86 | - added support for hierarchical display of tests based on their package 87 | - fixed utest reporting with multiple asserts ([#17](https://github.com/vshaxe/haxe-test-adapter/issues/17)) 88 | 89 | ## 1.2.5 (September 24, 2019) 90 | 91 | - fixed version check and compatibility with utest 1.10.0 92 | 93 | ## 1.2.4 (September 4, 2019) 94 | 95 | - fixed compatibility with Haxe 4.0.0-rc.4 96 | 97 | ## 1.2.3 (April 5, 2019) 98 | 99 | - fixed tests being grayed out with Test Explorer UI 2.9.0+ 100 | 101 | ## 1.2.2 (March 4, 2019) 102 | 103 | - fixed all tests being executed when debugging individual tests ([#13](https://github.com/vshaxe/haxe-test-adapter/pull/13)) 104 | 105 | ## 1.2.1 (February 28, 2019) 106 | 107 | - added `-D test-adapter-filter` for custom name matching 108 | - extended name matching for position recording to parent types ([#12](https://github.com/vshaxe/haxe-test-adapter/pull/12)) 109 | - improved position recording to no longer rely on name matching for utest, buddy and haxe.unit 110 | - improved handling of test suites with identical names where possible ([#9](https://github.com/vshaxe/haxe-test-adapter/pull/9)) 111 | 112 | ## 1.2.0 (February 23, 2019) 113 | 114 | - added support for the [hexUnit](https://github.com/DoclerLabs/hexUnit) test framework 115 | - added support for the [tink_unittest](https://github.com/haxetink/tink_unittest) test framework 116 | - fixed test-adapter setup with spaces in username 117 | - improved behavior during code completion 118 | 119 | ## 1.1.0 (February 14, 2019) 120 | 121 | - added support for the [buddy](https://github.com/ciscoheat/buddy) test framework 122 | - fixed results + decorations of removed tests sticking around 123 | 124 | ## 1.0.1 (February 13, 2019) 125 | 126 | - fixed compatibility with utest 1.9.2 127 | 128 | ## 1.0.0 (February 12, 2019) 129 | 130 | - initial release 131 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Haxe Test Explorer for Visual Studio Code 2 | 3 | A VSCode test controller for Haxe. 4 | 5 | ![VSCode test controller for Haxe](images/demo.gif) 6 | 7 | ## Features 8 | 9 | * Records [munit](https://github.com/massiveinteractive/MassiveUnit), [utest](https://github.com/haxe-utest/utest), [buddy](https://github.com/ciscoheat/buddy), [hexUnit](https://github.com/DoclerLabs/hexUnit), [tink_unittest](https://github.com/haxetink/tink_unittest) and [haxe.unit](https://api.haxe.org/haxe/unit/TestRunner.html) test results as JSON files 10 | * Shows latest test results in VSCode 11 | * Supports filtering / running individual tests directly from VSCode 12 | * Supports Haxe 3.4.7 and 4+ (detection of test function line numbers only works with Haxe 4) 13 | * Supports multi-root workspaces 14 | * Currently only works for Node.js and sys targets 15 | 16 | ## Usage 17 | 18 | A small sample project for each supported framework can be found in the [samples](https://github.com/vshaxe/haxe-test-adapter/tree/master/samples) directory. 19 | 20 | You can run your tests by clicking the button in the "Test" tab of the activity bar. The command that it runs can be configured via `settings.json`: 21 | 22 | ```json 23 | "haxeTestExplorer.testCommand": [ 24 | "${haxe}", 25 | "test.hxml", 26 | "-lib", 27 | "test-adapter" 28 | ] 29 | ``` 30 | 31 | As you can see, by default it assumes the presence of a `test.hxml` that compiles and runs the tests. Additionally, the `test-adapter` library is injected. It adds hooks to the different testing frameworks to record the test results in a `.unittest` folder in your workspace. 32 | 33 | While the `test-adapter` library itself ships with the extension and is set up automatically, you still need to install a dependency: 34 | 35 | ```hxml 36 | haxelib install json2object 37 | ``` 38 | 39 | `.unittest` should be added to your `.gitignore`. You might also want to hide it from VSCode's file explorer by adding this to your global settings: 40 | 41 | ```json 42 | "files.exclude": { 43 | "**/.unittest": true 44 | } 45 | ``` 46 | 47 | ### Debugging 48 | 49 | It's also possible to debug tests using a launch configuration from `launch.json`. Which one should be used can be configured with this setting: 50 | 51 | ```json 52 | "haxeTestExplorer.launchConfiguration": "Debug" 53 | ``` 54 | 55 | Unlike with `testCommand` for _running_ tests, `-lib test-adapter` can't be injected automatically for _debugging_. Add `-lib test-adapter` directly to your HXML file if you want results to be recorded / filtering to work while debugging. 56 | 57 | ### Detection of test positions 58 | 59 | Note that for `munit`, `hexUnit` and `tink_unittest`, the test-adapter library relies on a class name filter to detect the positions of tests. This simply defaults to `~/Test/` and is checked against the names of classes and implemented interfaces anywhere in the hierarchy of a class. 60 | 61 | You can customize the filter with `-D test-adapter-filter=`. Check `.unittest/positions.json` to see what positions were recorded. 62 | 63 | For `utest`, test detection only works when `utest.ITest` is implemented / `utest.TestCase` is extended. If this is not the case, utest will print a warning. 64 | 65 | ### Coverage 66 | 67 | to enable coverage runs `haxeTestExplorer.enableCoverageUI` needs to be set to `true` (default). Haxe test explorer will show a "Run Tests with Coverage" button, which will then try to run the command configured through `"haxeTestExplorer.coverageCommand"`. it defaults to: 68 | 69 | ```json 70 | "haxeTestExplorer.coverageCommand": [ 71 | "${haxe}", 72 | "testCoverage.hxml", 73 | "-lib", 74 | "test-adapter" 75 | ] 76 | ``` 77 | 78 | make sure your coverage run produces an LCOV file, you can configure the file name through `haxeTestExplorer.lcovPath` setting. it defaults to `lcov.info` in your project root. 79 | 80 | if you are using instrument library for coverage you don't need to set `haxeTestExplorer.lcovPath`, because it auto-configures (requires at least instrument 1.3.0). 81 | 82 | once your coverage run completes, VSCode should enable and show "TEST COVERAGE" view and also show file coverage in your "EXPLORER" view, as well as coloured line numbers in covered files. 83 | 84 | in case there is a delay between generating test results and writing your LCOV file you can set a wait time in milliseconds via `haxeTestExplorer.waitForCoverage` setting (default: `2000` ms). test explorer will delay showing test and coverage results to ensure both of them are ready when updating UI. 85 | 86 | ### Attributable Coverage 87 | 88 | when running Coverage with instrument library (1.3.0 and higher) test-adapter will automatically collect and generate coverage results per testcase. which means you can filter and view indiviual coverage results and see which testcase generated what coverage for your source files. you can also view unfiltered coverage results produced by all tests included in your most recent coverage run. 89 | 90 | you can disable attributable coverage filters by setting `haxeTestExplorer.enableAttributableCoverage` to `false` (default: `true`). instrument and test-adapter will still generate attributable coverage results, but it won't show filtering UI and you won't be able to dive into individual coverage generated by each testcase. 91 | 92 | use `-D disable-attributable-coverage` to disable attributable coverage data collection when using test-adapter library in combination with instrument library. 93 | 94 | ## Build from sources 95 | 96 | ```bash 97 | cd ~/.vscode/extensions 98 | git clone https://github.com/vshaxe/haxe-test-adapter 99 | cd haxe-test-adapter 100 | npm install 101 | npx haxe build.hxml 102 | 103 | haxelib dev test-adapter test-adapter 104 | ``` 105 | 106 | If you open the project in VSCode, the default `display.hxml` assumes you have all supported test frameworks installed. If you just want code completion for the sources of the extension itself, or the non-framework-specific parts of `test-adapter`, you can select `build.hxml` as your active Haxe configuration instead. 107 | -------------------------------------------------------------------------------- /build.hxml: -------------------------------------------------------------------------------- 1 | -lib hxnodejs 2 | -lib vscode 3 | -lib vshaxe 4 | -lib json2object 5 | -lib simple_lcov 6 | -cp src 7 | -cp test-adapter 8 | -js bin/main.js 9 | -D js-es=6 10 | # -debug 11 | HaxeTestController 12 | -------------------------------------------------------------------------------- /checkstyle.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "INFO", 3 | "checks": [ 4 | { 5 | "type": "ArrayAccess" 6 | }, 7 | { 8 | "type": "ArrayLiteral" 9 | }, 10 | { 11 | "props": { 12 | "format": "^(e)$" 13 | }, 14 | "type": "CatchParameterName" 15 | }, 16 | { 17 | "type": "DefaultComesLast" 18 | }, 19 | { 20 | "type": "DocCommentStyle" 21 | }, 22 | { 23 | "type": "ERegLiteral" 24 | }, 25 | { 26 | "type": "EmptyPackage" 27 | }, 28 | { 29 | "type": "FieldDocComment", 30 | "props": { 31 | "tokens": [ 32 | "CLASS_DEF" 33 | ], 34 | "severity": "IGNORE" 35 | } 36 | }, 37 | { 38 | "props": { 39 | "max": 2000 40 | }, 41 | "type": "FileLength" 42 | }, 43 | { 44 | "props": { 45 | "option": "upperCase" 46 | }, 47 | "type": "HexadecimalLiteral" 48 | }, 49 | { 50 | "props": { 51 | "allowMarkerInterfaces": true, 52 | "allowProperties": true 53 | }, 54 | "type": "Interface" 55 | }, 56 | { 57 | "props": { 58 | "max": 160, 59 | "ignorePattern": "(^@desc)|(LONG LINE TEST)" 60 | }, 61 | "type": "LineLength" 62 | }, 63 | { 64 | "props": { 65 | "listeners": [ 66 | "addEventListener", 67 | "addListener", 68 | "on", 69 | "once" 70 | ], 71 | "format": "^_?[a-z][a-zA-Z0-9]*$" 72 | }, 73 | "type": "ListenerName" 74 | }, 75 | { 76 | "props": { 77 | "ignoreExtern": true, 78 | "format": "^[a-z][a-zA-Z0-9]*$" 79 | }, 80 | "type": "LocalVariableName" 81 | }, 82 | { 83 | "props": { 84 | "ignoreExtern": true, 85 | "format": "^[A-Z][a-z]+(?:[A-Z][a-z]+)*$", 86 | "tokens": [ 87 | "ENUM" 88 | ] 89 | }, 90 | "type": "MemberName" 91 | }, 92 | { 93 | "props": { 94 | "maxPrivate": 50, 95 | "maxPublic": 50, 96 | "maxTotal": 50 97 | }, 98 | "type": "MethodCount" 99 | }, 100 | { 101 | "props": { 102 | "ignoreExtern": true, 103 | "format": "^[a-z][a-zA-Z0-9]*$" 104 | }, 105 | "type": "MethodName" 106 | }, 107 | { 108 | "props": { 109 | "modifiers": [ 110 | "MACRO", 111 | "OVERRIDE", 112 | "PUBLIC_PRIVATE", 113 | "STATIC", 114 | "INLINE", 115 | "DYNAMIC" 116 | ] 117 | }, 118 | "type": "ModifierOrder" 119 | }, 120 | { 121 | "props": { 122 | "minLength": 2, 123 | "ignore": "^\\s+$", 124 | "allowDuplicates": 3 125 | }, 126 | "type": "MultipleStringLiterals" 127 | }, 128 | { 129 | "type": "MultipleVariableDeclarations" 130 | }, 131 | { 132 | "props": { 133 | "allowSingleLineStatement": true, 134 | "tokens": [ 135 | "FOR", 136 | "IF", 137 | "ELSE_IF", 138 | "WHILE", 139 | "DO_WHILE" 140 | ] 141 | }, 142 | "type": "NeedBraces" 143 | }, 144 | { 145 | "type": "NestedIfDepth" 146 | }, 147 | { 148 | "type": "NestedTryDepth" 149 | }, 150 | { 151 | "props": { 152 | "ignoreExtern": true, 153 | "format": "^(_|[a-z][a-zA-Z0-9]*$)" 154 | }, 155 | "type": "ParameterName" 156 | }, 157 | { 158 | "props": { 159 | "max": 8, 160 | "ignoreOverriddenMethods": false 161 | }, 162 | "type": "ParameterNumber" 163 | }, 164 | { 165 | "type": "RedundantModifier" 166 | }, 167 | { 168 | "type": "RedundantAllowMeta" 169 | }, 170 | { 171 | "type": "RedundantAccessMeta" 172 | }, 173 | { 174 | "props": { 175 | "tokens": [ 176 | "," 177 | ], 178 | "option": "eol" 179 | }, 180 | "type": "SeparatorWrap" 181 | }, 182 | { 183 | "type": "SimplifyBooleanExpression" 184 | }, 185 | { 186 | "type": "SimplifyBooleanReturn" 187 | }, 188 | { 189 | "props": { 190 | "spaceIfCondition": "should", 191 | "spaceAroundBinop": true, 192 | "spaceForLoop": "should", 193 | "ignoreRangeOperator": true, 194 | "spaceWhileLoop": "should", 195 | "spaceCatch": "should", 196 | "spaceSwitchCase": "should", 197 | "noSpaceAroundUnop": true 198 | }, 199 | "type": "Spacing" 200 | }, 201 | { 202 | "props": { 203 | "allowException": true, 204 | "policy": "doubleAndInterpolation" 205 | }, 206 | "type": "StringLiteral" 207 | }, 208 | { 209 | "type": "TODOComment" 210 | }, 211 | { 212 | "type": "TabForAligning" 213 | }, 214 | { 215 | "type": "Trace" 216 | }, 217 | { 218 | "type": "TypeDocComment", 219 | "props": { 220 | "tokens": [ 221 | "CLASS_DEF", 222 | "INTERFACE_DEF" 223 | ], 224 | "severity": "IGNORE" 225 | } 226 | }, 227 | { 228 | "props": { 229 | "ignoreExtern": true, 230 | "format": "^[A-Z]+[a-zA-Z0-9]*$" 231 | }, 232 | "type": "TypeName" 233 | }, 234 | { 235 | "type": "UnnecessaryConstructor" 236 | } 237 | ], 238 | "exclude": { 239 | "path": "RELATIVE_TO_PROJECT", 240 | "all": [], 241 | "MultipleStringLiterals": [ 242 | "config" 243 | ] 244 | } 245 | } -------------------------------------------------------------------------------- /haxe_libraries/hxjsonast.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxjsonast#1.1.0" into hxjsonast/1.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxjsonast/1.1.0/haxelib/src 3 | -D hxjsonast=1.1.0 -------------------------------------------------------------------------------- /haxe_libraries/hxnodejs.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxnodejs#12.2.0" into hxnodejs/12.2.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxnodejs/12.2.0/haxelib/src 3 | -D hxnodejs=12.2.0 4 | --macro allowPackage('sys') 5 | # should behave like other target defines and not be defined in macro context 6 | --macro define('nodejs') 7 | --macro _internal.SuppressDeprecated.run() 8 | -------------------------------------------------------------------------------- /haxe_libraries/json2object.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/elnabo/json2object#a75859de1e966c09e73591b6c9186086c143fe60" into json2object/3.11.0/github/a75859de1e966c09e73591b6c9186086c143fe60 2 | -lib hxjsonast 3 | -cp ${HAXE_LIBCACHE}/json2object/3.11.0/github/a75859de1e966c09e73591b6c9186086c143fe60/src 4 | -D json2object=3.11.0 -------------------------------------------------------------------------------- /haxe_libraries/simple_lcov.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/simple_lcov#1.0.0" into simple_lcov/1.0.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/simple_lcov/1.0.0/haxelib/src 3 | -D simple_lcov=1.0.0 -------------------------------------------------------------------------------- /haxe_libraries/vscode.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/vshaxe/vscode-extern#a5b8a3616b8295037af7db23ed495d21dc3a78e8" into vscode/1.97.0/github/a5b8a3616b8295037af7db23ed495d21dc3a78e8 2 | -lib hxnodejs 3 | -cp ${HAXE_LIBCACHE}/vscode/1.97.0/github/a5b8a3616b8295037af7db23ed495d21dc3a78e8/src 4 | -D vscode=1.97.0 -------------------------------------------------------------------------------- /haxe_libraries/vshaxe.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/vshaxe#2.23.0" into vshaxe/2.23.0/haxelib 2 | -lib vscode 3 | -cp ${HAXE_LIBCACHE}/vshaxe/2.23.0/haxelib/src 4 | -D vshaxe=2.23.0 -------------------------------------------------------------------------------- /hxformat.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /images/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vshaxe/haxe-test-adapter/114421daf1f128751bd3b40084553541b6de96c3/images/demo.gif -------------------------------------------------------------------------------- /images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vshaxe/haxe-test-adapter/114421daf1f128751bd3b40084553541b6de96c3/images/icon.png -------------------------------------------------------------------------------- /makeReleaseZip.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | npm install 4 | npx lix download 5 | npx lix use haxe 4.3.6 6 | 7 | npx haxe build.hxml 8 | 9 | rm -f test-adapter.zip 10 | (cd test-adapter; zip -9 -r -q ../test-adapter.zip .) 11 | zip -9 -r -q test-adapter.zip images README.md LICENSE.md CHANGELOG.md -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "haxe-test-adapter", 3 | "version": "3.0.1", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "haxe-test-adapter", 9 | "version": "3.0.1", 10 | "hasInstallScript": true, 11 | "license": "MIT", 12 | "devDependencies": { 13 | "lix": "^15.12.4" 14 | }, 15 | "engines": { 16 | "nadako.vshaxe": "^2.23.0", 17 | "vscode": "^1.96.0" 18 | } 19 | }, 20 | "node_modules/lix": { 21 | "version": "15.12.4", 22 | "resolved": "https://registry.npmjs.org/lix/-/lix-15.12.4.tgz", 23 | "integrity": "sha512-xfwGQrXXNba9BM7VcP2u9WvElBYgGJW+1gviaFqJH5OUFPAhwv8TZNk5f+Yew4pyKOmMqshdUYgk9+d3U6P6kw==", 24 | "dev": true, 25 | "hasInstallScript": true, 26 | "license": "MIT", 27 | "bin": { 28 | "haxe": "bin/haxeshim.js", 29 | "haxelib": "bin/haxelibshim.js", 30 | "lix": "bin/lix.js", 31 | "neko": "bin/nekoshim.js" 32 | } 33 | } 34 | }, 35 | "dependencies": { 36 | "lix": { 37 | "version": "15.12.4", 38 | "resolved": "https://registry.npmjs.org/lix/-/lix-15.12.4.tgz", 39 | "integrity": "sha512-xfwGQrXXNba9BM7VcP2u9WvElBYgGJW+1gviaFqJH5OUFPAhwv8TZNk5f+Yew4pyKOmMqshdUYgk9+d3U6P6kw==", 40 | "dev": true 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "haxe-test-adapter", 3 | "displayName": "Haxe Test Explorer", 4 | "description": "Run your Haxe tests in the Sidebar of Visual Studio Code", 5 | "icon": "images/icon.png", 6 | "author": "Alexander Blum ", 7 | "publisher": "vshaxe", 8 | "version": "3.0.1", 9 | "license": "MIT", 10 | "homepage": "https://github.com/vshaxe/haxe-test-adapter", 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/vshaxe/haxe-test-adapter.git" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/vshaxe/haxe-test-adapter/issues" 17 | }, 18 | "badges": [ 19 | { 20 | "url": "https://api.travis-ci.org/vshaxe/haxe-test-adapter.svg?branch=master", 21 | "href": "https://travis-ci.org/vshaxe/haxe-test-adapter", 22 | "description": "Travis CI Status" 23 | } 24 | ], 25 | "categories": [ 26 | "Other" 27 | ], 28 | "keywords": [ 29 | "test", 30 | "testing", 31 | "haxe" 32 | ], 33 | "scripts": { 34 | "vscode:prepublish": "haxe build.hxml", 35 | "postinstall": "lix download" 36 | }, 37 | "main": "bin/main.js", 38 | "devDependencies": { 39 | "lix": "^15.12.4" 40 | }, 41 | "engines": { 42 | "vscode": "^1.96.0", 43 | "nadako.vshaxe": "^2.23.0" 44 | }, 45 | "extensionDependencies": [ 46 | "nadako.vshaxe" 47 | ], 48 | "activationEvents": [ 49 | "onLanguage:haxe", 50 | "onView:test" 51 | ], 52 | "contributes": { 53 | "commands": [ 54 | { 55 | "title": "Setup", 56 | "command": "haxeTestExplorer.setup", 57 | "category": "Haxe Test Explorer" 58 | } 59 | ], 60 | "configuration": { 61 | "title": "Haxe Test Explorer", 62 | "properties": { 63 | "haxeTestExplorer.testCommand": { 64 | "type": "array", 65 | "scope": "resource", 66 | "default": [ 67 | "${haxe}", 68 | "test.hxml", 69 | "-lib", 70 | "test-adapter" 71 | ], 72 | "markdownDescription": "Command for building and running the tests. `${haxe}` is replaced with `\"haxe.executable\"`.", 73 | "items": { 74 | "type": "string" 75 | } 76 | }, 77 | "haxeTestExplorer.coverageCommand": { 78 | "type": "array", 79 | "scope": "resource", 80 | "default": [ 81 | "${haxe}", 82 | "testCoverage.hxml", 83 | "-lib", 84 | "test-adapter" 85 | ], 86 | "markdownDescription": "Command for building and running the tests with coverage. `${haxe}` is replaced with `\"haxe.executable\"`.", 87 | "items": { 88 | "type": "string" 89 | } 90 | }, 91 | "haxeTestExplorer.enableCoverageUI": { 92 | "type": "boolean", 93 | "scope": "resource", 94 | "default": "true", 95 | "markdownDescription": "enable coverage UI" 96 | }, 97 | "haxeTestExplorer.enableAttributableCoverage": { 98 | "type": "boolean", 99 | "scope": "resource", 100 | "default": "true", 101 | "markdownDescription": "enable attributable coverage, e.g. coverage per testcase - requires instrument lib" 102 | }, 103 | "haxeTestExplorer.lcovPath": { 104 | "type": "string", 105 | "scope": "resource", 106 | "default": "lcov.info", 107 | "markdownDescription": "path and filename for your LCOV coverage report, when not using instrument lib" 108 | }, 109 | "haxeTestExplorer.waitForCoverage": { 110 | "type": "integer", 111 | "scope": "resource", 112 | "default": 2000, 113 | "markdownDescription": "time in milliseconds to wait for coverage results file to be ready" 114 | }, 115 | "haxeTestExplorer.launchConfiguration": { 116 | "type": "string", 117 | "scope": "resource", 118 | "default": "Debug", 119 | "markdownDescription": "Name of the launch configuration to use for debugging. (make sure you add `--lib test-adapter` to your compiler arguments)" 120 | } 121 | } 122 | } 123 | }, 124 | "__metadata": { 125 | "id": "9e0a4c2a-45e9-4f5d-9981-3fadda76009b", 126 | "publisherDisplayName": "Haxe Foundation", 127 | "publisherId": "bdf58939-bf37-40d4-9543-90fcc14fd490" 128 | } 129 | } -------------------------------------------------------------------------------- /samples/all-samples.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "buddy" 5 | }, 6 | { 7 | "path": "haxeunit" 8 | }, 9 | { 10 | "path": "hexunit" 11 | }, 12 | { 13 | "path": "munit" 14 | }, 15 | { 16 | "path": "tink_unittest" 17 | }, 18 | { 19 | "path": "utest" 20 | }, 21 | { 22 | "path": "munit-mcover" 23 | }, 24 | { 25 | "path": "tink_unittest-instrument" 26 | }, 27 | { 28 | "path": "utest-instrument" 29 | }, 30 | { 31 | "path": "munit-instrument" 32 | }, 33 | { 34 | "path": "buddy-instrument" 35 | } 36 | ], 37 | "settings": {} 38 | } -------------------------------------------------------------------------------- /samples/buddy-instrument/.haxerc: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.3.6", 3 | "resolveLibs": "scoped" 4 | } -------------------------------------------------------------------------------- /samples/buddy-instrument/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug", 6 | "type": "haxe-eval", 7 | "request": "launch", 8 | "args": ["test.hxml", "--lib", "test-adapter"] 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /samples/buddy-instrument/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[haxe]": { 3 | "editor.formatOnSave": true, 4 | "editor.formatOnPaste": true 5 | }, 6 | "haxeTestExplorer.coverageCommand": [ 7 | "${haxe}", 8 | "testCoverage.hxml", 9 | "-lib", 10 | "test-adapter" 11 | ], 12 | "haxeTestExplorer.lcovPath": "lcov.info", 13 | "haxeTestExplorer.enableAttributableCoverage": true, 14 | "haxeTestExplorer.enableCoverageUI": true, 15 | } -------------------------------------------------------------------------------- /samples/buddy-instrument/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "haxe", 6 | "args": "active configuration", 7 | "group": { 8 | "kind": "build", 9 | "isDefault": true 10 | } 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/buddy-instrument/haxe_libraries/asynctools.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/asynctools#0.1.0" into asynctools/0.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/asynctools/0.1.0/haxelib/ 3 | -D asynctools=0.1.0 -------------------------------------------------------------------------------- /samples/buddy-instrument/haxe_libraries/buddy.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/buddy#2.13.0" into buddy/2.13.0/haxelib 2 | -lib asynctools 3 | -lib promhx 4 | -cp ${HAXE_LIBCACHE}/buddy/2.13.0/haxelib/ 5 | -D buddy=2.13.0 -------------------------------------------------------------------------------- /samples/buddy-instrument/haxe_libraries/hxjsonast.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxjsonast#1.1.0" into hxjsonast/1.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxjsonast/1.1.0/haxelib/src 3 | -D hxjsonast=1.1.0 -------------------------------------------------------------------------------- /samples/buddy-instrument/haxe_libraries/hxnodejs.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxnodejs#12.1.0" into hxnodejs/12.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxnodejs/12.1.0/haxelib/src 3 | -D hxnodejs=12.1.0 4 | --macro allowPackage('sys') 5 | # should behave like other target defines and not be defined in macro context 6 | --macro define('nodejs') 7 | --macro _internal.SuppressDeprecated.run() 8 | -------------------------------------------------------------------------------- /samples/buddy-instrument/haxe_libraries/instrument.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/instrument#1.4.0" into instrument/1.4.0/haxelib 2 | -lib safety 3 | -cp ${HAXE_LIBCACHE}/instrument/1.4.0/haxelib/src 4 | -D instrument=1.4.0 -------------------------------------------------------------------------------- /samples/buddy-instrument/haxe_libraries/json2object.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/elnabo/json2object#a75859de1e966c09e73591b6c9186086c143fe60" into json2object/3.11.0/github/a75859de1e966c09e73591b6c9186086c143fe60 2 | -lib hxjsonast 3 | -cp ${HAXE_LIBCACHE}/json2object/3.11.0/github/a75859de1e966c09e73591b6c9186086c143fe60/src 4 | -D json2object=3.11.0 -------------------------------------------------------------------------------- /samples/buddy-instrument/haxe_libraries/promhx.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/promhx#1.1.0" into promhx/1.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/promhx/1.1.0/haxelib/src/main 3 | -D promhx=1.1.0 -------------------------------------------------------------------------------- /samples/buddy-instrument/haxe_libraries/safety.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/safety#1.1.2" into safety/1.1.2/haxelib 2 | -cp ${HAXE_LIBCACHE}/safety/1.1.2/haxelib/src 3 | -D safety=1.1.2 -------------------------------------------------------------------------------- /samples/buddy-instrument/haxe_libraries/test-adapter.hxml: -------------------------------------------------------------------------------- 1 | -lib json2object 2 | -cp ../../test-adapter 3 | -D test-adapter=2.0.7 4 | ${SCOPE_DIR}/../../test-adapter/extraParams.hxml 5 | --macro Sys.println("haxe_libraries/test-adapter.hxml:3: [Warning] Using dev version of library test-adapter") -------------------------------------------------------------------------------- /samples/buddy-instrument/src/Main.hx: -------------------------------------------------------------------------------- 1 | class Main { 2 | public function new() { 3 | doNothing(); 4 | } 5 | 6 | public function doSomething(condition:Bool) { 7 | switch (condition) { 8 | case true: 9 | doNothing(); 10 | case false: 11 | doNothing(); 12 | default: 13 | doNothing(); 14 | } 15 | 16 | switch (condition) { 17 | case true: 18 | case false: 19 | doNothing(); 20 | default: 21 | } 22 | 23 | if (condition) { 24 | doNothing(); 25 | } 26 | // test 27 | 28 | doNothing(); 29 | 30 | if (!condition) { 31 | doNothing(); 32 | } 33 | doNothing(); 34 | 35 | if (condition) { 36 | doNothing(); 37 | return false; 38 | } else { 39 | doNothing(); 40 | } 41 | doNothing(); 42 | return true; 43 | } 44 | 45 | public function doSomethingFullCoverage(condition:Bool) { 46 | if (condition) { 47 | doNothing(); 48 | return false; 49 | } else { 50 | doNothing(); 51 | } 52 | 53 | doNothing(); 54 | return true; 55 | } 56 | 57 | public function doNothing() { 58 | return true; 59 | } 60 | 61 | public function doMoreNothing() { 62 | // test 63 | return true; 64 | } 65 | 66 | static function main() { 67 | new Main(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /samples/buddy-instrument/test.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -cp tests 3 | -lib buddy 4 | -x Test 5 | -------------------------------------------------------------------------------- /samples/buddy-instrument/testCoverage.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -cp tests 3 | -lib buddy 4 | -lib instrument 5 | -x Test 6 | 7 | -D coverage-console-summary-reporter 8 | 9 | --macro instrument.Instrumentation.coverage([''], ['src'], []) 10 | -D instrument-quiet 11 | -------------------------------------------------------------------------------- /samples/buddy-instrument/tests/Test.hx: -------------------------------------------------------------------------------- 1 | import buddy.BuddySuite; 2 | import buddy.SuitesRunner; 3 | 4 | using buddy.Should; 5 | 6 | class Test extends BuddySuite { 7 | public static function main() { 8 | new SuitesRunner([new Test()]).run().then(function(runner) { 9 | #if instrument 10 | instrument.coverage.Coverage.endCoverage(); 11 | #end 12 | }); 13 | } 14 | 15 | public function new() { 16 | describe("TestMain", { 17 | it("should do nothing", { 18 | var main = new Main(); 19 | 20 | main.doNothing().should.be(true); 21 | }); 22 | it("should do something", { 23 | var main = new Main(); 24 | 25 | main.doSomething(false).should.be(true); 26 | }); 27 | 28 | it("should do something with full coverage", { 29 | var main = new Main(); 30 | 31 | main.doSomethingFullCoverage(false).should.be(true); 32 | main.doSomethingFullCoverage(true).should.be(false); 33 | }); 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /samples/buddy/.haxerc: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.3.6", 3 | "resolveLibs": "scoped" 4 | } -------------------------------------------------------------------------------- /samples/buddy/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug", 6 | "type": "haxe-eval", 7 | "request": "launch", 8 | "args": ["test.hxml", "--lib", "test-adapter"] 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /samples/buddy/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[haxe]": { 3 | "editor.formatOnSave": true, 4 | "editor.formatOnPaste": true 5 | } 6 | } -------------------------------------------------------------------------------- /samples/buddy/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "haxe", 6 | "args": "active configuration", 7 | "group": { 8 | "kind": "build", 9 | "isDefault": true 10 | } 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/buddy/haxe_libraries/asynctools.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/asynctools#0.1.0" into asynctools/0.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/asynctools/0.1.0/haxelib/ 3 | -D asynctools=0.1.0 -------------------------------------------------------------------------------- /samples/buddy/haxe_libraries/buddy.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/buddy#2.13.0" into buddy/2.13.0/haxelib 2 | -lib asynctools 3 | -lib promhx 4 | -cp ${HAXE_LIBCACHE}/buddy/2.13.0/haxelib/ 5 | -D buddy=2.13.0 -------------------------------------------------------------------------------- /samples/buddy/haxe_libraries/hxjsonast.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxjsonast#1.1.0" into hxjsonast/1.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxjsonast/1.1.0/haxelib/src 3 | -D hxjsonast=1.1.0 -------------------------------------------------------------------------------- /samples/buddy/haxe_libraries/json2object.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/json2object#3.11.0" into json2object/3.11.0/haxelib 2 | -lib hxjsonast 3 | -cp ${HAXE_LIBCACHE}/json2object/3.11.0/haxelib/src 4 | -D json2object=3.11.0 -------------------------------------------------------------------------------- /samples/buddy/haxe_libraries/promhx.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/promhx#1.1.0" into promhx/1.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/promhx/1.1.0/haxelib/src/main 3 | -D promhx=1.1.0 -------------------------------------------------------------------------------- /samples/buddy/haxe_libraries/test-adapter.hxml: -------------------------------------------------------------------------------- 1 | -lib json2object 2 | -cp ../../test-adapter 3 | -D test-adapter=2.0.7 4 | ${SCOPE_DIR}/../../test-adapter/extraParams.hxml 5 | --macro Sys.println("haxe_libraries/test-adapter.hxml:3: [Warning] Using dev version of library test-adapter") -------------------------------------------------------------------------------- /samples/buddy/src/Main.hx: -------------------------------------------------------------------------------- 1 | import buddy.BuddySuite; 2 | import buddy.SuitesRunner; 3 | import tests.TestCase3; 4 | 5 | using buddy.Should; 6 | 7 | class Main extends BuddySuite { 8 | public static function main() { 9 | new SuitesRunner([new Main(), new TestCase3()]).run(); 10 | } 11 | 12 | public function new() { 13 | describe("TestCase", { 14 | it("testSuccess", { 15 | Sys.sleep(Math.random()); 16 | "A".should.be("A"); 17 | }); 18 | 19 | it("testFailure", { 20 | Sys.sleep(Math.random()); 21 | "A".should.be("B"); 22 | }); 23 | 24 | it("testError", { 25 | Sys.sleep(Math.random()); 26 | throw "error"; 27 | }); 28 | 29 | it("testEmpty", { 30 | Sys.sleep(Math.random()); 31 | }); 32 | }); 33 | 34 | describe("TestCase2", { 35 | it("testSuccess", { 36 | "A".should.be("A"); 37 | }); 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /samples/buddy/src/tests/TestCase3.hx: -------------------------------------------------------------------------------- 1 | package tests; 2 | 3 | using buddy.Should; 4 | 5 | class TestCase3 extends buddy.SingleSuite { 6 | public function new() { 7 | describe("TestCase", { 8 | it("testSuccess", { 9 | "A".should.be("A"); 10 | }); 11 | }); 12 | describe("TestCase3", { 13 | describe("TestCase", { 14 | it("testSuccess", { 15 | "A".should.be("A"); 16 | }); 17 | }); 18 | it("testSuccess", { 19 | "A".should.be("A"); 20 | }); 21 | describe("innerTestCase3", { 22 | it("testSuccess", { 23 | "A".should.be("A"); 24 | }); 25 | it("testSuccess2", { 26 | "A".should.be("A"); 27 | }); 28 | }); 29 | it("testPending", {}); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /samples/buddy/test.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -lib buddy 3 | -x Main -------------------------------------------------------------------------------- /samples/haxeunit/.haxerc: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.3.6", 3 | "resolveLibs": "scoped" 4 | } -------------------------------------------------------------------------------- /samples/haxeunit/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug", 6 | "type": "haxe-eval", 7 | "request": "launch", 8 | "args": ["test.hxml", "--lib", "test-adapter"] 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /samples/haxeunit/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[haxe]": { 3 | "editor.formatOnSave": true, 4 | "editor.formatOnPaste": true 5 | } 6 | } -------------------------------------------------------------------------------- /samples/haxeunit/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "haxe", 6 | "args": "active configuration", 7 | "group": { 8 | "kind": "build", 9 | "isDefault": true 10 | } 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/haxeunit/haxe_libraries/hx3compat.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hx3compat#1.0.3" into hx3compat/1.0.3/haxelib 2 | -cp ${HAXE_LIBCACHE}/hx3compat/1.0.3/haxelib/std 3 | -D hx3compat=1.0.3 -------------------------------------------------------------------------------- /samples/haxeunit/haxe_libraries/hxjsonast.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxjsonast#1.1.0" into hxjsonast/1.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxjsonast/1.1.0/haxelib/src 3 | -D hxjsonast=1.1.0 -------------------------------------------------------------------------------- /samples/haxeunit/haxe_libraries/json2object.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/json2object#3.11.0" into json2object/3.11.0/haxelib 2 | -lib hxjsonast 3 | -cp ${HAXE_LIBCACHE}/json2object/3.11.0/haxelib/src 4 | -D json2object=3.11.0 -------------------------------------------------------------------------------- /samples/haxeunit/haxe_libraries/test-adapter.hxml: -------------------------------------------------------------------------------- 1 | -lib json2object 2 | -cp ../../test-adapter 3 | -D test-adapter=2.0.7 4 | ${SCOPE_DIR}/../../test-adapter/extraParams.hxml 5 | --macro Sys.println("haxe_libraries/test-adapter.hxml:3: [Warning] Using dev version of library test-adapter") -------------------------------------------------------------------------------- /samples/haxeunit/src/Main.hx: -------------------------------------------------------------------------------- 1 | import tests.TestCase3; 2 | 3 | class Main { 4 | static function main() { 5 | var runner = new haxe.unit.TestRunner(); 6 | runner.add(new TestCase()); 7 | runner.add(new TestCase2()); 8 | runner.add(new tests.TestCase()); 9 | runner.add(new TestCase3()); 10 | runner.run(); 11 | } 12 | } 13 | 14 | class TestCase extends haxe.unit.TestCase { 15 | function testSuccess() { 16 | Sys.sleep(Math.random()); 17 | assertTrue(true); 18 | } 19 | 20 | function testFailure() { 21 | Sys.sleep(Math.random()); 22 | assertEquals("A", "B"); 23 | } 24 | 25 | function testError() { 26 | Sys.sleep(Math.random()); 27 | throw "error"; 28 | } 29 | 30 | function testEmpty() { 31 | Sys.sleep(Math.random()); 32 | } 33 | } 34 | 35 | class TestCase2 extends haxe.unit.TestCase { 36 | function testSuccess() { 37 | assertTrue(true); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /samples/haxeunit/src/tests/TestCase.hx: -------------------------------------------------------------------------------- 1 | package tests; 2 | 3 | class TestCase extends haxe.unit.TestCase { 4 | function testSuccess() { 5 | assertTrue(true); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /samples/haxeunit/src/tests/TestCase3.hx: -------------------------------------------------------------------------------- 1 | package tests; 2 | 3 | class TestCase3 extends haxe.unit.TestCase { 4 | function testSuccess() { 5 | assertTrue(true); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /samples/haxeunit/test.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -lib hx3compat 3 | -x Main -------------------------------------------------------------------------------- /samples/hexunit/.haxerc: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.3.6", 3 | "resolveLibs": "scoped" 4 | } -------------------------------------------------------------------------------- /samples/hexunit/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug", 6 | "type": "haxe-eval", 7 | "request": "launch", 8 | "args": ["test.hxml", "--lib", "test-adapter"] 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /samples/hexunit/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[haxe]": { 3 | "editor.formatOnSave": true, 4 | "editor.formatOnPaste": true 5 | } 6 | } -------------------------------------------------------------------------------- /samples/hexunit/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "haxe", 6 | "args": "active configuration", 7 | "group": { 8 | "kind": "build", 9 | "isDefault": true 10 | } 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/hexunit/haxe_libraries/hexcore.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hexcore#0.35.0" into hexcore/0.35.0/haxelib 2 | -lib hexlog 3 | -lib tink_macro 4 | -cp ${HAXE_LIBCACHE}/hexcore/0.35.0/haxelib/src 5 | -D hexcore=0.35.0 -------------------------------------------------------------------------------- /samples/hexunit/haxe_libraries/hexlog.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hexlog#0.35.0" into hexlog/0.35.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hexlog/0.35.0/haxelib/src 3 | -D hexlog=0.35.0 -------------------------------------------------------------------------------- /samples/hexunit/haxe_libraries/hexunit.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hexunit#0.35.0" into hexunit/0.35.0/haxelib 2 | -lib hexcore 3 | -cp ${HAXE_LIBCACHE}/hexunit/0.35.0/haxelib/src 4 | -D hexunit=0.35.0 -------------------------------------------------------------------------------- /samples/hexunit/haxe_libraries/hxjsonast.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxjsonast#1.1.0" into hxjsonast/1.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxjsonast/1.1.0/haxelib/src 3 | -D hxjsonast=1.1.0 -------------------------------------------------------------------------------- /samples/hexunit/haxe_libraries/json2object.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/json2object#3.11.0" into json2object/3.11.0/haxelib 2 | -lib hxjsonast 3 | -cp ${HAXE_LIBCACHE}/json2object/3.11.0/haxelib/src 4 | -D json2object=3.11.0 -------------------------------------------------------------------------------- /samples/hexunit/haxe_libraries/test-adapter.hxml: -------------------------------------------------------------------------------- 1 | -lib json2object 2 | -cp ../../test-adapter 3 | -D test-adapter=2.0.7 4 | ${SCOPE_DIR}/../../test-adapter/extraParams.hxml 5 | --macro Sys.println("haxe_libraries/test-adapter.hxml:3: [Warning] Using dev version of library test-adapter") -------------------------------------------------------------------------------- /samples/hexunit/haxe_libraries/tink_core.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_core#2.1.1" into tink_core/2.1.1/haxelib 2 | -cp ${HAXE_LIBCACHE}/tink_core/2.1.1/haxelib/src 3 | -D tink_core=2.1.1 -------------------------------------------------------------------------------- /samples/hexunit/haxe_libraries/tink_macro.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_macro#0.16.1" into tink_macro/0.16.1/haxelib 2 | -lib tink_core 3 | -cp ${HAXE_LIBCACHE}/tink_macro/0.16.1/haxelib/src 4 | -D tink_macro=0.16.1 -------------------------------------------------------------------------------- /samples/hexunit/src/Main.hx: -------------------------------------------------------------------------------- 1 | import hex.unittest.assertion.Assert; 2 | import hex.unittest.notifier.TraceNotifier; 3 | import hex.unittest.runner.ExMachinaUnitCore; 4 | import tests.TestCase3; 5 | 6 | class Main { 7 | static function main() { 8 | var emu = new ExMachinaUnitCore(); 9 | 10 | emu.addListener(new TraceNotifier()); 11 | emu.addTest(TestCase); 12 | emu.addTest(TestCase2); 13 | tests.TestCase.addSelf(emu); 14 | emu.addTest(TestCase3); 15 | emu.run(); 16 | } 17 | } 18 | 19 | class TestCase { 20 | @Test 21 | function testSuccess() { 22 | Sys.sleep(Math.random()); 23 | Assert.isTrue(true); 24 | } 25 | 26 | @Test 27 | function testFailure() { 28 | Sys.sleep(Math.random()); 29 | Assert.equals("A", "B"); 30 | } 31 | 32 | @Test 33 | function testError() { 34 | Sys.sleep(Math.random()); 35 | throw "failure"; 36 | } 37 | 38 | @Test 39 | function testEmpty() { 40 | Sys.sleep(Math.random()); 41 | } 42 | 43 | @Ignore 44 | function testIgnore() {} 45 | } 46 | 47 | class TestCase2 { 48 | @Test 49 | function testSuccess() { 50 | Assert.isTrue(true); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /samples/hexunit/src/tests/TestCase.hx: -------------------------------------------------------------------------------- 1 | package tests; 2 | 3 | import hex.unittest.runner.ExMachinaUnitCore; 4 | import hex.unittest.assertion.Assert; 5 | 6 | class TestCase { 7 | @Test 8 | function testSuccess() { 9 | Assert.isTrue(true); 10 | } 11 | 12 | public static function addSelf(emu:ExMachinaUnitCore) { 13 | emu.addTest(TestCase); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/hexunit/src/tests/TestCase3.hx: -------------------------------------------------------------------------------- 1 | package tests; 2 | 3 | import hex.unittest.assertion.Assert; 4 | 5 | class TestCase3 { 6 | @Test 7 | function testSuccess() { 8 | Assert.isTrue(true); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /samples/hexunit/test.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -lib hexunit 3 | -x Main -------------------------------------------------------------------------------- /samples/munit-instrument/.haxerc: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.3.6", 3 | "resolveLibs": "scoped" 4 | } -------------------------------------------------------------------------------- /samples/munit-instrument/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug", 6 | "type": "haxe-eval", 7 | "request": "launch", 8 | "args": ["test.hxml", "--lib", "test-adapter"] 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /samples/munit-instrument/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[haxe]": { 3 | "editor.formatOnSave": true, 4 | "editor.formatOnPaste": true 5 | }, 6 | "haxeTestExplorer.coverageCommand": [ 7 | "${haxe}", 8 | "testCoverage.hxml", 9 | "-lib", 10 | "test-adapter" 11 | ], 12 | "haxeTestExplorer.lcovPath": "lcov.info", 13 | "haxeTestExplorer.enableAttributableCoverage": true, 14 | "haxeTestExplorer.enableCoverageUI": true, 15 | } -------------------------------------------------------------------------------- /samples/munit-instrument/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "haxe", 6 | "args": "active configuration", 7 | "group": { 8 | "kind": "build", 9 | "isDefault": true 10 | } 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/munit-instrument/haxe_libraries/hxjsonast.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxjsonast#1.1.0" into hxjsonast/1.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxjsonast/1.1.0/haxelib/src 3 | -D hxjsonast=1.1.0 -------------------------------------------------------------------------------- /samples/munit-instrument/haxe_libraries/instrument.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/instrument#1.4.0" into instrument/1.4.0/haxelib 2 | -lib safety 3 | -cp ${HAXE_LIBCACHE}/instrument/1.4.0/haxelib/src 4 | -D instrument=1.4.0 -------------------------------------------------------------------------------- /samples/munit-instrument/haxe_libraries/json2object.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/elnabo/json2object#a75859de1e966c09e73591b6c9186086c143fe60" into json2object/3.11.0/github/a75859de1e966c09e73591b6c9186086c143fe60 2 | -lib hxjsonast 3 | -cp ${HAXE_LIBCACHE}/json2object/3.11.0/github/a75859de1e966c09e73591b6c9186086c143fe60/src 4 | -D json2object=3.11.0 -------------------------------------------------------------------------------- /samples/munit-instrument/haxe_libraries/mconsole.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/mconsole#1.6.0" into mconsole/1.6.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/mconsole/1.6.0/haxelib/ 3 | -D mconsole=1.6.0 -------------------------------------------------------------------------------- /samples/munit-instrument/haxe_libraries/mcover.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/mcover#2.2.2" into mcover/2.2.2/haxelib 2 | -lib mconsole 3 | -lib munit 4 | -cp ${HAXE_LIBCACHE}/mcover/2.2.2/haxelib/ 5 | -D mcover=2.2.2 -------------------------------------------------------------------------------- /samples/munit-instrument/haxe_libraries/mlib.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/mlib#2.0.3" into mlib/2.0.3/haxelib 2 | # @run: haxelib run-dir mlib "${HAXE_LIBCACHE}/mlib/2.0.3/haxelib" 3 | -cp ${HAXE_LIBCACHE}/mlib/2.0.3/haxelib/ 4 | -D mlib=2.0.3 -------------------------------------------------------------------------------- /samples/munit-instrument/haxe_libraries/munit.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/AlexHaxe/MassiveUnit#5d964248de93dc97de34e1e9c05e0fd59377c1e5" into MassiveUnit/0.0.0/github/5d964248de93dc97de34e1e9c05e0fd59377c1e5 2 | -lib mlib 3 | -cp ${HAXE_LIBCACHE}/MassiveUnit/0.0.0/github/5d964248de93dc97de34e1e9c05e0fd59377c1e5/src 4 | -D munit=2.3.5 -------------------------------------------------------------------------------- /samples/munit-instrument/haxe_libraries/safety.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/safety#1.1.2" into safety/1.1.2/haxelib 2 | -cp ${HAXE_LIBCACHE}/safety/1.1.2/haxelib/src 3 | -D safety=1.1.2 -------------------------------------------------------------------------------- /samples/munit-instrument/haxe_libraries/test-adapter.hxml: -------------------------------------------------------------------------------- 1 | -lib json2object 2 | -cp ../../test-adapter 3 | -D test-adapter=2.0.7 4 | ${SCOPE_DIR}/../../test-adapter/extraParams.hxml 5 | --macro Sys.println("haxe_libraries/test-adapter.hxml:3: [Warning] Using dev version of library test-adapter") -------------------------------------------------------------------------------- /samples/munit-instrument/src/Main.hx: -------------------------------------------------------------------------------- 1 | class Main { 2 | public function new() { 3 | doNothing(); 4 | } 5 | 6 | public function doSomething(condition:Bool) { 7 | switch (condition) { 8 | case true: 9 | doNothing(); 10 | case false: 11 | doNothing(); 12 | default: 13 | doNothing(); 14 | } 15 | 16 | switch (condition) { 17 | case true: 18 | case false: 19 | doNothing(); 20 | default: 21 | } 22 | 23 | if (condition) { 24 | doNothing(); 25 | } 26 | // test 27 | 28 | doNothing(); 29 | 30 | if (!condition) { 31 | doNothing(); 32 | } 33 | doNothing(); 34 | 35 | if (condition) { 36 | doNothing(); 37 | return false; 38 | } else { 39 | doNothing(); 40 | } 41 | doNothing(); 42 | return true; 43 | } 44 | 45 | public function doSomethingFullCoverage(condition:Bool) { 46 | if (condition) { 47 | doNothing(); 48 | return false; 49 | } else { 50 | doNothing(); 51 | } 52 | 53 | doNothing(); 54 | return true; 55 | } 56 | 57 | public function doNothing() { 58 | return true; 59 | } 60 | 61 | public function doMoreNothing() { 62 | // test 63 | return true; 64 | } 65 | 66 | static function main() { 67 | new Main(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /samples/munit-instrument/test.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -cp tests 3 | -lib munit 4 | -x Test -------------------------------------------------------------------------------- /samples/munit-instrument/testCoverage.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -cp tests 3 | -lib munit 4 | -lib instrument 5 | -x Test 6 | 7 | -D coverage-console-summary-reporter 8 | 9 | --macro instrument.Instrumentation.coverage([''], ['src'], []) 10 | -D instrument-quiet 11 | -------------------------------------------------------------------------------- /samples/munit-instrument/tests/Test.hx: -------------------------------------------------------------------------------- 1 | import massive.munit.Assert; 2 | import massive.munit.TestRunner; 3 | import massive.munit.client.RichPrintClient; 4 | 5 | class Test { 6 | static function main() { 7 | var client = new RichPrintClient(); 8 | var runner = new TestRunner(client); 9 | runner.run([TestSuite]); 10 | 11 | #if instrument 12 | instrument.coverage.Coverage.endCoverage(); 13 | #end 14 | } 15 | } 16 | 17 | class TestSuite extends massive.munit.TestSuite { 18 | public function new() { 19 | super(); 20 | add(TestMain); 21 | } 22 | } 23 | 24 | class TestMain { 25 | @Test 26 | function testDoNothing() { 27 | var main = new Main(); 28 | 29 | Assert.isTrue(main.doNothing()); 30 | } 31 | 32 | @Test 33 | function testDoSomething() { 34 | var main = new Main(); 35 | 36 | Assert.isTrue(main.doSomething(false)); 37 | } 38 | 39 | @Test 40 | function testDoSomethingFullCoverage() { 41 | var main = new Main(); 42 | 43 | Assert.isTrue(main.doSomethingFullCoverage(false)); 44 | Assert.isFalse(main.doSomethingFullCoverage(true)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /samples/munit-mcover/.haxerc: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.3.6", 3 | "resolveLibs": "scoped" 4 | } -------------------------------------------------------------------------------- /samples/munit-mcover/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug", 6 | "type": "haxe-eval", 7 | "request": "launch", 8 | "args": ["test.hxml", "--lib", "test-adapter"] 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /samples/munit-mcover/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[haxe]": { 3 | "editor.formatOnSave": true, 4 | "editor.formatOnPaste": true 5 | }, 6 | "haxeTestExplorer.coverageCommand": [ 7 | "${haxe}", 8 | "testCoverage.hxml", 9 | "-lib", 10 | "test-adapter" 11 | ], 12 | "haxeTestExplorer.lcovPath": "lcov.info", 13 | "haxeTestExplorer.enableAttributableCoverage": true, 14 | "haxeTestExplorer.enableCoverageUI": true, 15 | } -------------------------------------------------------------------------------- /samples/munit-mcover/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "haxe", 6 | "args": "active configuration", 7 | "group": { 8 | "kind": "build", 9 | "isDefault": true 10 | } 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/munit-mcover/haxe_libraries/hxjsonast.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxjsonast#1.1.0" into hxjsonast/1.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxjsonast/1.1.0/haxelib/src 3 | -D hxjsonast=1.1.0 -------------------------------------------------------------------------------- /samples/munit-mcover/haxe_libraries/json2object.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/elnabo/json2object#a75859de1e966c09e73591b6c9186086c143fe60" into json2object/3.11.0/github/a75859de1e966c09e73591b6c9186086c143fe60 2 | -lib hxjsonast 3 | -cp ${HAXE_LIBCACHE}/json2object/3.11.0/github/a75859de1e966c09e73591b6c9186086c143fe60/src 4 | -D json2object=3.11.0 -------------------------------------------------------------------------------- /samples/munit-mcover/haxe_libraries/mconsole.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/mconsole#1.6.0" into mconsole/1.6.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/mconsole/1.6.0/haxelib/ 3 | -D mconsole=1.6.0 -------------------------------------------------------------------------------- /samples/munit-mcover/haxe_libraries/mcover.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/AlexHaxe/mcover#263b0aff3280a406102d8cb6e9b1f614492e559a" into mcover/0.0.0/github/263b0aff3280a406102d8cb6e9b1f614492e559a 2 | -cp ${HAXE_LIBCACHE}/mcover/0.0.0/github/263b0aff3280a406102d8cb6e9b1f614492e559a/src 3 | -D mcover=0.0.0 -------------------------------------------------------------------------------- /samples/munit-mcover/haxe_libraries/mlib.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/mlib#2.0.3" into mlib/2.0.3/haxelib 2 | # @run: haxelib run-dir mlib "${HAXE_LIBCACHE}/mlib/2.0.3/haxelib" 3 | -cp ${HAXE_LIBCACHE}/mlib/2.0.3/haxelib/ 4 | -D mlib=2.0.3 -------------------------------------------------------------------------------- /samples/munit-mcover/haxe_libraries/munit.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/AlexHaxe/MassiveUnit#5d964248de93dc97de34e1e9c05e0fd59377c1e5" into MassiveUnit/0.0.0/github/5d964248de93dc97de34e1e9c05e0fd59377c1e5 2 | -lib mlib 3 | -cp ${HAXE_LIBCACHE}/MassiveUnit/0.0.0/github/5d964248de93dc97de34e1e9c05e0fd59377c1e5/src 4 | -D munit=2.3.5 -------------------------------------------------------------------------------- /samples/munit-mcover/haxe_libraries/test-adapter.hxml: -------------------------------------------------------------------------------- 1 | -lib json2object 2 | -cp ../../test-adapter 3 | -D test-adapter=2.0.7 4 | ${SCOPE_DIR}/../../test-adapter/extraParams.hxml 5 | --macro Sys.println("haxe_libraries/test-adapter.hxml:3: [Warning] Using dev version of library test-adapter") -------------------------------------------------------------------------------- /samples/munit-mcover/src/Main.hx: -------------------------------------------------------------------------------- 1 | class Main { 2 | public function new() { 3 | doNothing(); 4 | } 5 | 6 | public function doSomething(condition:Bool) { 7 | switch (condition) { 8 | case true: 9 | doNothing(); 10 | case false: 11 | doNothing(); 12 | default: 13 | doNothing(); 14 | } 15 | 16 | switch (condition) { 17 | case true: 18 | case false: 19 | doNothing(); 20 | default: 21 | } 22 | 23 | if (condition) { 24 | doNothing(); 25 | } 26 | // test 27 | 28 | doNothing(); 29 | 30 | if (!condition) { 31 | doNothing(); 32 | } 33 | doNothing(); 34 | 35 | if (condition) { 36 | doNothing(); 37 | return false; 38 | } else { 39 | doNothing(); 40 | } 41 | doNothing(); 42 | return true; 43 | } 44 | 45 | public function doSomethingFullCoverage(condition:Bool) { 46 | if (condition) { 47 | doNothing(); 48 | return false; 49 | } else { 50 | doNothing(); 51 | } 52 | 53 | doNothing(); 54 | return true; 55 | } 56 | 57 | public function doNothing() { 58 | return true; 59 | } 60 | 61 | public function doMoreNothing() { 62 | // test 63 | return true; 64 | } 65 | 66 | static function main() { 67 | new Main(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /samples/munit-mcover/test.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -cp tests 3 | -lib munit 4 | -x Test -------------------------------------------------------------------------------- /samples/munit-mcover/testCoverage.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -cp tests 3 | -lib mcover 4 | -lib munit 5 | -x Test 6 | 7 | -D unittest 8 | 9 | --macro mcover.MCover.coverage([''], ['src'], []) 10 | -------------------------------------------------------------------------------- /samples/munit-mcover/tests/Test.hx: -------------------------------------------------------------------------------- 1 | import massive.munit.Assert; 2 | import massive.munit.TestRunner; 3 | import massive.munit.client.RichPrintClient; 4 | #if mcover 5 | import mcover.coverage.munit.client.MCoverPrintClient; 6 | #end 7 | 8 | class Test { 9 | static function main() { 10 | #if mcover 11 | var client:MCoverPrintClient = new MCoverPrintClient(); 12 | mcover.coverage.MCoverage.getLogger().addClient(new mcover.coverage.client.LcovPrintClient("mcover unittests")); 13 | #else 14 | var client = new RichPrintClient(); 15 | #end 16 | 17 | var runner = new TestRunner(client); 18 | runner.run([TestSuite]); 19 | } 20 | } 21 | 22 | class TestSuite extends massive.munit.TestSuite { 23 | public function new() { 24 | super(); 25 | add(TestMain); 26 | } 27 | } 28 | 29 | class TestMain { 30 | @Test 31 | function testDoNothing() { 32 | var main = new Main(); 33 | 34 | Assert.isTrue(main.doNothing()); 35 | } 36 | 37 | @Test 38 | function testDoSomething() { 39 | var main = new Main(); 40 | 41 | Assert.isTrue(main.doSomething(false)); 42 | } 43 | 44 | @Test 45 | function testDoSomethingFullCoverage() { 46 | var main = new Main(); 47 | 48 | Assert.isTrue(main.doSomethingFullCoverage(false)); 49 | Assert.isFalse(main.doSomethingFullCoverage(true)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /samples/munit/.haxerc: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.3.6", 3 | "resolveLibs": "scoped" 4 | } -------------------------------------------------------------------------------- /samples/munit/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug", 6 | "type": "haxe-eval", 7 | "request": "launch", 8 | "args": ["test.hxml", "--lib", "test-adapter"] 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /samples/munit/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[haxe]": { 3 | "editor.formatOnSave": true, 4 | "editor.formatOnPaste": true 5 | } 6 | } -------------------------------------------------------------------------------- /samples/munit/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "haxe", 6 | "args": "active configuration", 7 | "group": { 8 | "kind": "build", 9 | "isDefault": true 10 | } 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/munit/haxe_libraries/hxjsonast.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxjsonast#1.1.0" into hxjsonast/1.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxjsonast/1.1.0/haxelib/src 3 | -D hxjsonast=1.1.0 -------------------------------------------------------------------------------- /samples/munit/haxe_libraries/json2object.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/json2object#3.11.0" into json2object/3.11.0/haxelib 2 | -lib hxjsonast 3 | -cp ${HAXE_LIBCACHE}/json2object/3.11.0/haxelib/src 4 | -D json2object=3.11.0 -------------------------------------------------------------------------------- /samples/munit/haxe_libraries/mconsole.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/mconsole#1.6.0" into mconsole/1.6.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/mconsole/1.6.0/haxelib/ 3 | -D mconsole=1.6.0 -------------------------------------------------------------------------------- /samples/munit/haxe_libraries/mcover.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/mcover#2.2.2" into mcover/2.2.2/haxelib 2 | -lib mconsole 3 | -lib munit 4 | -cp ${HAXE_LIBCACHE}/mcover/2.2.2/haxelib/ 5 | -D mcover=2.2.2 -------------------------------------------------------------------------------- /samples/munit/haxe_libraries/mlib.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/mlib#2.0.3" into mlib/2.0.3/haxelib 2 | # @run: haxelib run-dir mlib "${HAXE_LIBCACHE}/mlib/2.0.3/haxelib" 3 | -cp ${HAXE_LIBCACHE}/mlib/2.0.3/haxelib/ 4 | -D mlib=2.0.3 -------------------------------------------------------------------------------- /samples/munit/haxe_libraries/munit.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/munit#2.3.5" into munit/2.3.5/haxelib 2 | # @run: haxelib run-dir munit "${HAXE_LIBCACHE}/munit/2.3.5/haxelib" 3 | -lib mcover 4 | -lib mlib 5 | -cp ${HAXE_LIBCACHE}/munit/2.3.5/haxelib/ 6 | -D munit=2.3.5 -------------------------------------------------------------------------------- /samples/munit/haxe_libraries/test-adapter.hxml: -------------------------------------------------------------------------------- 1 | -lib json2object 2 | -cp ../../test-adapter 3 | -D test-adapter=2.0.7 4 | ${SCOPE_DIR}/../../test-adapter/extraParams.hxml 5 | --macro Sys.println("haxe_libraries/test-adapter.hxml:3: [Warning] Using dev version of library test-adapter") -------------------------------------------------------------------------------- /samples/munit/src/Main.hx: -------------------------------------------------------------------------------- 1 | import massive.munit.Assert; 2 | import massive.munit.TestRunner; 3 | import massive.munit.client.RichPrintClient; 4 | import tests.TestSuite2; 5 | 6 | class Main { 7 | static function main() { 8 | var client = new RichPrintClient(); 9 | var runner = new TestRunner(client); 10 | runner.run([TestSuite, TestSuite2]); 11 | } 12 | } 13 | 14 | class TestSuite extends massive.munit.TestSuite { 15 | public function new() { 16 | super(); 17 | add(TestCase); 18 | add(TestCase2); 19 | } 20 | } 21 | 22 | class TestCase { 23 | @Test 24 | function testSuccess() { 25 | Sys.sleep(Math.random()); 26 | Assert.isTrue(true); 27 | } 28 | 29 | @Test 30 | function testFailure() { 31 | Sys.sleep(Math.random()); 32 | Assert.areEqual("A", "B"); 33 | } 34 | 35 | @Test 36 | function testError() { 37 | Sys.sleep(Math.random()); 38 | throw "error"; 39 | } 40 | 41 | @Test 42 | function testEmpty() { 43 | Sys.sleep(Math.random()); 44 | } 45 | 46 | @Test @Ignore("Description") 47 | function testIgnore() {} 48 | } 49 | 50 | class TestCase2 { 51 | @Test 52 | function testSuccess() { 53 | Assert.isTrue(true); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /samples/munit/src/tests/TestCase.hx: -------------------------------------------------------------------------------- 1 | package tests; 2 | 3 | import massive.munit.Assert; 4 | 5 | class TestCase { 6 | @Test 7 | function testSuccess() { 8 | Assert.isTrue(true); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /samples/munit/src/tests/TestCase3.hx: -------------------------------------------------------------------------------- 1 | package tests; 2 | 3 | import massive.munit.Assert; 4 | 5 | class TestCase3 { 6 | @Test 7 | function testSuccess() { 8 | Assert.isTrue(true); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /samples/munit/src/tests/TestSuite2.hx: -------------------------------------------------------------------------------- 1 | package tests; 2 | 3 | class TestSuite2 extends massive.munit.TestSuite { 4 | public function new() { 5 | super(); 6 | add(TestCase); 7 | add(TestCase3); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/munit/test.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -lib munit 3 | -x Main -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/.haxerc: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.3.6", 3 | "resolveLibs": "scoped" 4 | } -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug", 6 | "type": "haxe-eval", 7 | "request": "launch", 8 | "args": ["test.hxml", "--lib", "test-adapter"] 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[haxe]": { 3 | "editor.formatOnSave": true, 4 | "editor.formatOnPaste": true 5 | }, 6 | "haxeTestExplorer.coverageCommand": [ 7 | "${haxe}", 8 | "testCoverage.hxml", 9 | "-lib", 10 | "test-adapter" 11 | ] 12 | } -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "haxe", 6 | "args": "active configuration", 7 | "group": { 8 | "kind": "build", 9 | "isDefault": true 10 | } 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/haxe_libraries/ansi.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/ansi#1.0.0" into ansi/1.0.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/ansi/1.0.0/haxelib/src 3 | -D ansi=1.0.0 -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/haxe_libraries/hxjsonast.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxjsonast#1.1.0" into hxjsonast/1.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxjsonast/1.1.0/haxelib/src 3 | -D hxjsonast=1.1.0 -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/haxe_libraries/instrument.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/instrument#1.4.0" into instrument/1.4.0/haxelib 2 | -lib safety 3 | -cp ${HAXE_LIBCACHE}/instrument/1.4.0/haxelib/src 4 | -D instrument=1.4.0 -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/haxe_libraries/json2object.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/elnabo/json2object#a75859de1e966c09e73591b6c9186086c143fe60" into json2object/3.11.0/github/a75859de1e966c09e73591b6c9186086c143fe60 2 | -lib hxjsonast 3 | -cp ${HAXE_LIBCACHE}/json2object/3.11.0/github/a75859de1e966c09e73591b6c9186086c143fe60/src 4 | -D json2object=3.11.0 -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/haxe_libraries/safety.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/safety#1.1.2" into safety/1.1.2/haxelib 2 | -cp ${HAXE_LIBCACHE}/safety/1.1.2/haxelib/src 3 | -D safety=1.1.2 -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/haxe_libraries/test-adapter.hxml: -------------------------------------------------------------------------------- 1 | -lib json2object 2 | -cp ../../test-adapter 3 | -D test-adapter=2.0.7 4 | ${SCOPE_DIR}/../../test-adapter/extraParams.hxml 5 | --macro Sys.println("haxe_libraries/test-adapter.hxml:3: [Warning] Using dev version of library test-adapter") -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/haxe_libraries/tink_core.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_core#2.1.1" into tink_core/2.1.1/haxelib 2 | -cp ${HAXE_LIBCACHE}/tink_core/2.1.1/haxelib/src 3 | -D tink_core=2.1.1 -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/haxe_libraries/tink_macro.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxetink/tink_macro#08249260f9f6d5c015dd1434ee68d199e960c0d4" into tink_macro/1.0.4/github/08249260f9f6d5c015dd1434ee68d199e960c0d4 2 | -lib tink_core 3 | -cp ${HAXE_LIBCACHE}/tink_macro/1.0.4/github/08249260f9f6d5c015dd1434ee68d199e960c0d4/src 4 | -D tink_macro=1.0.4 -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/haxe_libraries/tink_priority.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_priority#0.1.4" into tink_priority/0.1.4/haxelib 2 | -cp ${HAXE_LIBCACHE}/tink_priority/0.1.4/haxelib/src 3 | -D tink_priority=0.1.4 -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/haxe_libraries/tink_streams.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_streams#0.4.0" into tink_streams/0.4.0/haxelib 2 | -lib tink_core 3 | -cp ${HAXE_LIBCACHE}/tink_streams/0.4.0/haxelib/src 4 | -D tink_streams=0.4.0 5 | # temp for development, delete this file when pure branch merged 6 | -D pure -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/haxe_libraries/tink_syntaxhub.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_syntaxhub#0.6.1" into tink_syntaxhub/0.6.1/haxelib 2 | -lib tink_macro 3 | -lib tink_priority 4 | -cp ${HAXE_LIBCACHE}/tink_syntaxhub/0.6.1/haxelib/src 5 | -D tink_syntaxhub=0.6.1 6 | --macro tink.SyntaxHub.use() -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/haxe_libraries/tink_testrunner.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_testrunner#0.9.0" into tink_testrunner/0.9.0/haxelib 2 | -lib ansi 3 | -lib tink_macro 4 | -lib tink_streams 5 | -cp ${HAXE_LIBCACHE}/tink_testrunner/0.9.0/haxelib/src 6 | -D tink_testrunner=0.9.0 -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/haxe_libraries/tink_unittest.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_unittest#0.8.0" into tink_unittest/0.8.0/haxelib 2 | -lib tink_syntaxhub 3 | -lib tink_testrunner 4 | -cp ${HAXE_LIBCACHE}/tink_unittest/0.8.0/haxelib/src 5 | -D tink_unittest=0.8.0 6 | --macro tink.unit.AssertionBufferInjector.use() -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/src/Main.hx: -------------------------------------------------------------------------------- 1 | class Main { 2 | public function new() { 3 | doNothing(); 4 | } 5 | 6 | public function doSomething(condition:Bool) { 7 | switch (condition) { 8 | case true: 9 | doNothing(); 10 | case false: 11 | doNothing(); 12 | default: 13 | doNothing(); 14 | } 15 | 16 | switch (condition) { 17 | case true: 18 | case false: 19 | doNothing(); 20 | default: 21 | } 22 | 23 | if (condition) { 24 | doNothing(); 25 | } 26 | // test 27 | 28 | doNothing(); 29 | 30 | if (!condition) { 31 | doNothing(); 32 | } 33 | doNothing(); 34 | 35 | if (condition) { 36 | doNothing(); 37 | return false; 38 | } else { 39 | doNothing(); 40 | } 41 | doNothing(); 42 | return true; 43 | } 44 | 45 | public function doSomethingFullCoverage(condition:Bool) { 46 | if (condition) { 47 | doNothing(); 48 | return false; 49 | } else { 50 | doNothing(); 51 | } 52 | 53 | doNothing(); 54 | return true; 55 | } 56 | 57 | public function doNothing() { 58 | return true; 59 | } 60 | 61 | public function doMoreNothing() { 62 | // test 63 | return true; 64 | } 65 | 66 | static function main() { 67 | new Main(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/test.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -cp tests 3 | -lib tink_unittest 4 | -x Test -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/testCoverage.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -cp tests 3 | -lib tink_unittest 4 | -lib instrument 5 | -x Test 6 | 7 | -D coverage-console-summary-reporter 8 | 9 | --macro instrument.Instrumentation.coverage([''], ['src'], []) 10 | -D instrument-quiet 11 | -------------------------------------------------------------------------------- /samples/tink_unittest-instrument/tests/Test.hx: -------------------------------------------------------------------------------- 1 | import tink.testrunner.Runner; 2 | import tink.unit.*; 3 | import tink.unit.Assert; 4 | 5 | class Test { 6 | static function main() { 7 | Runner.run(TestBatch.make([new TestCase()])).handle(function(result) { 8 | #if instrument 9 | instrument.coverage.Coverage.endCoverage(); 10 | #end 11 | Runner.exit(result); 12 | }); 13 | } 14 | } 15 | 16 | @:asserts 17 | class TestCase { 18 | public function new() {} 19 | 20 | public function testDoNothing() { 21 | var main = new Main(); 22 | 23 | return Assert.assert(main.doNothing()); 24 | } 25 | 26 | public function testDoSomething() { 27 | var main = new Main(); 28 | 29 | return Assert.assert(main.doSomething(false)); 30 | } 31 | 32 | public function testDoSomethingFullCoverage() { 33 | var main = new Main(); 34 | 35 | return [ 36 | Assert.assert(main.doSomethingFullCoverage(false)), 37 | Assert.assert(main.doSomethingFullCoverage(true) == false) 38 | ]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /samples/tink_unittest/.haxerc: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.3.6", 3 | "resolveLibs": "scoped" 4 | } -------------------------------------------------------------------------------- /samples/tink_unittest/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug", 6 | "type": "haxe-eval", 7 | "request": "launch", 8 | "args": ["test.hxml", "--lib", "test-adapter"] 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /samples/tink_unittest/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[haxe]": { 3 | "editor.formatOnSave": true, 4 | "editor.formatOnPaste": true 5 | } 6 | } -------------------------------------------------------------------------------- /samples/tink_unittest/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "haxe", 6 | "args": "active configuration", 7 | "group": { 8 | "kind": "build", 9 | "isDefault": true 10 | } 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/tink_unittest/haxe_libraries/ansi.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/ansi#1.0.0" into ansi/1.0.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/ansi/1.0.0/haxelib/src 3 | -D ansi=1.0.0 -------------------------------------------------------------------------------- /samples/tink_unittest/haxe_libraries/hxjsonast.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxjsonast#1.1.0" into hxjsonast/1.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxjsonast/1.1.0/haxelib/src 3 | -D hxjsonast=1.1.0 -------------------------------------------------------------------------------- /samples/tink_unittest/haxe_libraries/json2object.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/json2object#3.11.0" into json2object/3.11.0/haxelib 2 | -lib hxjsonast 3 | -cp ${HAXE_LIBCACHE}/json2object/3.11.0/haxelib/src 4 | -D json2object=3.11.0 -------------------------------------------------------------------------------- /samples/tink_unittest/haxe_libraries/test-adapter.hxml: -------------------------------------------------------------------------------- 1 | -lib json2object 2 | -cp ../../test-adapter 3 | -D test-adapter=2.0.7 4 | ${SCOPE_DIR}/../../test-adapter/extraParams.hxml 5 | --macro Sys.println("haxe_libraries/test-adapter.hxml:3: [Warning] Using dev version of library test-adapter") -------------------------------------------------------------------------------- /samples/tink_unittest/haxe_libraries/tink_core.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_core#2.1.1" into tink_core/2.1.1/haxelib 2 | -cp ${HAXE_LIBCACHE}/tink_core/2.1.1/haxelib/src 3 | -D tink_core=2.1.1 -------------------------------------------------------------------------------- /samples/tink_unittest/haxe_libraries/tink_macro.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_macro#1.0.3" into tink_macro/1.0.3/haxelib 2 | -lib tink_core 3 | -cp ${HAXE_LIBCACHE}/tink_macro/1.0.3/haxelib/src 4 | -D tink_macro=1.0.3 -------------------------------------------------------------------------------- /samples/tink_unittest/haxe_libraries/tink_priority.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_priority#0.1.4" into tink_priority/0.1.4/haxelib 2 | -cp ${HAXE_LIBCACHE}/tink_priority/0.1.4/haxelib/src 3 | -D tink_priority=0.1.4 -------------------------------------------------------------------------------- /samples/tink_unittest/haxe_libraries/tink_streams.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_streams#0.4.0" into tink_streams/0.4.0/haxelib 2 | -lib tink_core 3 | -cp ${HAXE_LIBCACHE}/tink_streams/0.4.0/haxelib/src 4 | -D tink_streams=0.4.0 5 | # temp for development, delete this file when pure branch merged 6 | -D pure -------------------------------------------------------------------------------- /samples/tink_unittest/haxe_libraries/tink_syntaxhub.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_syntaxhub#0.6.1" into tink_syntaxhub/0.6.1/haxelib 2 | -lib tink_macro 3 | -lib tink_priority 4 | -cp ${HAXE_LIBCACHE}/tink_syntaxhub/0.6.1/haxelib/src 5 | -D tink_syntaxhub=0.6.1 6 | --macro tink.SyntaxHub.use() -------------------------------------------------------------------------------- /samples/tink_unittest/haxe_libraries/tink_testrunner.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_testrunner#0.9.0" into tink_testrunner/0.9.0/haxelib 2 | -lib ansi 3 | -lib tink_macro 4 | -lib tink_streams 5 | -cp ${HAXE_LIBCACHE}/tink_testrunner/0.9.0/haxelib/src 6 | -D tink_testrunner=0.9.0 -------------------------------------------------------------------------------- /samples/tink_unittest/haxe_libraries/tink_unittest.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/tink_unittest#0.8.0" into tink_unittest/0.8.0/haxelib 2 | -lib tink_syntaxhub 3 | -lib tink_testrunner 4 | -cp ${HAXE_LIBCACHE}/tink_unittest/0.8.0/haxelib/src 5 | -D tink_unittest=0.8.0 6 | --macro tink.unit.AssertionBufferInjector.use() -------------------------------------------------------------------------------- /samples/tink_unittest/src/Main.hx: -------------------------------------------------------------------------------- 1 | import tests.TestCase3; 2 | import tink.testrunner.Runner; 3 | import tink.unit.*; 4 | import tink.unit.Assert; 5 | 6 | class Main { 7 | static function main() { 8 | Runner.run(TestBatch.make([new TestCase(), new TestCase2(), new tests.TestCase(), new TestCase3()])).handle(Runner.exit); 9 | } 10 | } 11 | 12 | @:asserts 13 | class TestCase { 14 | public function new() {} 15 | 16 | public function testSuccess() { 17 | Sys.sleep(Math.random()); 18 | return Assert.assert(true); 19 | } 20 | 21 | public function testFailure() { 22 | Sys.sleep(Math.random()); 23 | return Assert.assert("A" == "B"); 24 | } 25 | 26 | public function testError() { 27 | Sys.sleep(Math.random()); 28 | return new tink.core.Error("failure"); 29 | } 30 | 31 | public function testEmpty() { 32 | Sys.sleep(Math.random()); 33 | return asserts.done(); 34 | } 35 | 36 | @:exclude 37 | public function testIgnore() {} 38 | } 39 | 40 | class TestCase2 { 41 | public function new() {} 42 | 43 | public function testSuccess() { 44 | return Assert.assert(true); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /samples/tink_unittest/src/tests/TestCase.hx: -------------------------------------------------------------------------------- 1 | package tests; 2 | 3 | import tink.unit.Assert; 4 | 5 | class TestCase { 6 | public function new() {} 7 | 8 | public function testSuccess() { 9 | return Assert.assert(true); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/tink_unittest/src/tests/TestCase3.hx: -------------------------------------------------------------------------------- 1 | package tests; 2 | 3 | import tink.unit.Assert; 4 | 5 | class TestCase3 { 6 | public function new() {} 7 | 8 | public function testSuccess() { 9 | return Assert.assert(true); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/tink_unittest/test.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -lib tink_unittest 3 | -x Main -------------------------------------------------------------------------------- /samples/utest-instrument/.haxerc: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.3.6", 3 | "resolveLibs": "scoped" 4 | } -------------------------------------------------------------------------------- /samples/utest-instrument/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug", 6 | "type": "haxe-eval", 7 | "request": "launch", 8 | "args": ["test.hxml", "--lib", "test-adapter"] 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /samples/utest-instrument/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[haxe]": { 3 | "editor.formatOnSave": true, 4 | "editor.formatOnPaste": true 5 | }, 6 | "haxeTestExplorer.coverageCommand": [ 7 | "${haxe}", 8 | "testCoverage.hxml", 9 | "-lib", 10 | "test-adapter" 11 | ], 12 | "haxeTestExplorer.lcovPath": "lcov.info", 13 | "haxeTestExplorer.enableAttributableCoverage": true, 14 | "haxeTestExplorer.enableCoverageUI": true, 15 | } -------------------------------------------------------------------------------- /samples/utest-instrument/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "haxe", 6 | "args": "active configuration", 7 | "group": { 8 | "kind": "build", 9 | "isDefault": true 10 | } 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/utest-instrument/haxe_libraries/hxjsonast.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxjsonast#1.1.0" into hxjsonast/1.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxjsonast/1.1.0/haxelib/src 3 | -D hxjsonast=1.1.0 -------------------------------------------------------------------------------- /samples/utest-instrument/haxe_libraries/instrument.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/instrument#1.4.0" into instrument/1.4.0/haxelib 2 | -lib safety 3 | -cp ${HAXE_LIBCACHE}/instrument/1.4.0/haxelib/src 4 | -D instrument=1.4.0 -------------------------------------------------------------------------------- /samples/utest-instrument/haxe_libraries/json2object.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/elnabo/json2object#a75859de1e966c09e73591b6c9186086c143fe60" into json2object/3.11.0/github/a75859de1e966c09e73591b6c9186086c143fe60 2 | -lib hxjsonast 3 | -cp ${HAXE_LIBCACHE}/json2object/3.11.0/github/a75859de1e966c09e73591b6c9186086c143fe60/src 4 | -D json2object=3.11.0 -------------------------------------------------------------------------------- /samples/utest-instrument/haxe_libraries/safety.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/safety#1.1.2" into safety/1.1.2/haxelib 2 | -cp ${HAXE_LIBCACHE}/safety/1.1.2/haxelib/src 3 | -D safety=1.1.2 -------------------------------------------------------------------------------- /samples/utest-instrument/haxe_libraries/test-adapter.hxml: -------------------------------------------------------------------------------- 1 | -lib json2object 2 | -cp ../../test-adapter 3 | -D test-adapter=2.0.7 4 | ${SCOPE_DIR}/../../test-adapter/extraParams.hxml 5 | --macro Sys.println("haxe_libraries/test-adapter.hxml:3: [Warning] Using dev version of library test-adapter") -------------------------------------------------------------------------------- /samples/utest-instrument/haxe_libraries/utest.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxe-utest/utest#bdb5fec4b8e77d9a3c079d9cfb108f29f153721a" into utest/2.0.0-alpha/github/bdb5fec4b8e77d9a3c079d9cfb108f29f153721a 2 | -cp ${HAXE_LIBCACHE}/utest/2.0.0-alpha/github/bdb5fec4b8e77d9a3c079d9cfb108f29f153721a/src 3 | -D utest=2.0.0-alpha 4 | --macro utest.utils.Macro.importEnvSettings() 5 | -------------------------------------------------------------------------------- /samples/utest-instrument/src/Main.hx: -------------------------------------------------------------------------------- 1 | class Main { 2 | public function new() { 3 | doNothing(); 4 | } 5 | 6 | public function doSomething(condition:Bool) { 7 | switch (condition) { 8 | case true: 9 | doNothing(); 10 | case false: 11 | doNothing(); 12 | default: 13 | doNothing(); 14 | } 15 | 16 | switch (condition) { 17 | case true: 18 | case false: 19 | doNothing(); 20 | default: 21 | } 22 | 23 | if (condition) { 24 | doNothing(); 25 | } 26 | // test 27 | 28 | doNothing(); 29 | 30 | if (!condition) { 31 | doNothing(); 32 | } 33 | doNothing(); 34 | 35 | if (condition) { 36 | doNothing(); 37 | return false; 38 | } else { 39 | doNothing(); 40 | } 41 | doNothing(); 42 | return true; 43 | } 44 | 45 | public function doSomethingFullCoverage(condition:Bool) { 46 | if (condition) { 47 | doNothing(); 48 | return false; 49 | } else { 50 | doNothing(); 51 | } 52 | 53 | doNothing(); 54 | return true; 55 | } 56 | 57 | public function doNothing() { 58 | return true; 59 | } 60 | 61 | public function doMoreNothing() { 62 | // test 63 | return true; 64 | } 65 | 66 | static function main() { 67 | new Main(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /samples/utest-instrument/test.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -cp tests 3 | -lib utest 4 | -x Test -------------------------------------------------------------------------------- /samples/utest-instrument/testCoverage.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -cp tests 3 | -lib utest 4 | -lib instrument 5 | -x Test 6 | 7 | # -D coverage-console-file-summary-reporter 8 | # -D coverage-console-package-summary-reporter 9 | # -D coverage-console-missing-reporter 10 | -D coverage-console-summary-reporter 11 | -D coverage-lcov-reporter 12 | 13 | --macro instrument.Instrumentation.coverage([''], ['src'], []) 14 | -D instrument-quiet 15 | -------------------------------------------------------------------------------- /samples/utest-instrument/tests/Test.hx: -------------------------------------------------------------------------------- 1 | import utest.Assert; 2 | import utest.ITest; 3 | import utest.Runner; 4 | import utest.ui.text.DiagnosticsReport; 5 | 6 | class Test { 7 | static function main() { 8 | var tests:Array = [new TestMain(),]; 9 | var runner:Runner = new Runner(); 10 | 11 | #if instrument 12 | runner.onComplete.add(_ -> { 13 | instrument.coverage.Coverage.endCoverage(); 14 | }); 15 | #end 16 | 17 | new DiagnosticsReport(runner); 18 | for (test in tests) { 19 | runner.addCase(test); 20 | } 21 | runner.run(); 22 | } 23 | } 24 | 25 | class TestMain implements ITest { 26 | public function new() {} 27 | 28 | function testDoNothing() { 29 | var main = new Main(); 30 | 31 | Assert.isTrue(main.doNothing()); 32 | } 33 | 34 | function testDoSomething() { 35 | var main = new Main(); 36 | 37 | Assert.isTrue(main.doSomething(false)); 38 | } 39 | 40 | function testDoSomethingFullCoverage() { 41 | var main = new Main(); 42 | 43 | Assert.isTrue(main.doSomethingFullCoverage(false)); 44 | Assert.isFalse(main.doSomethingFullCoverage(true)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /samples/utest/.haxerc: -------------------------------------------------------------------------------- 1 | { 2 | "version": "4.3.6", 3 | "resolveLibs": "scoped" 4 | } -------------------------------------------------------------------------------- /samples/utest/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug", 6 | "type": "haxe-eval", 7 | "request": "launch", 8 | "args": ["test.hxml", "--lib", "test-adapter"] 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /samples/utest/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "[haxe]": { 3 | "editor.formatOnSave": true, 4 | "editor.formatOnPaste": true 5 | } 6 | } -------------------------------------------------------------------------------- /samples/utest/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "haxe", 6 | "args": "active configuration", 7 | "group": { 8 | "kind": "build", 9 | "isDefault": true 10 | } 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /samples/utest/haxe_libraries/hxjsonast.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/hxjsonast#1.1.0" into hxjsonast/1.1.0/haxelib 2 | -cp ${HAXE_LIBCACHE}/hxjsonast/1.1.0/haxelib/src 3 | -D hxjsonast=1.1.0 -------------------------------------------------------------------------------- /samples/utest/haxe_libraries/json2object.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "haxelib:/json2object#3.11.0" into json2object/3.11.0/haxelib 2 | -lib hxjsonast 3 | -cp ${HAXE_LIBCACHE}/json2object/3.11.0/haxelib/src 4 | -D json2object=3.11.0 -------------------------------------------------------------------------------- /samples/utest/haxe_libraries/test-adapter.hxml: -------------------------------------------------------------------------------- 1 | -lib json2object 2 | -cp ../../test-adapter 3 | -D test-adapter=2.0.7 4 | ${SCOPE_DIR}/../../test-adapter/extraParams.hxml 5 | --macro Sys.println("haxe_libraries/test-adapter.hxml:3: [Warning] Using dev version of library test-adapter") -------------------------------------------------------------------------------- /samples/utest/haxe_libraries/utest.hxml: -------------------------------------------------------------------------------- 1 | # @install: lix --silent download "gh://github.com/haxe-utest/utest#bdb5fec4b8e77d9a3c079d9cfb108f29f153721a" into utest/2.0.0-alpha/github/bdb5fec4b8e77d9a3c079d9cfb108f29f153721a 2 | -cp ${HAXE_LIBCACHE}/utest/2.0.0-alpha/github/bdb5fec4b8e77d9a3c079d9cfb108f29f153721a/src 3 | -D utest=2.0.0-alpha 4 | --macro utest.utils.Macro.importEnvSettings() 5 | -------------------------------------------------------------------------------- /samples/utest/src/Main.hx: -------------------------------------------------------------------------------- 1 | import tests.TestCase3; 2 | import tests.pack.TestCase4; 3 | import utest.Assert; 4 | 5 | class Main { 6 | static function main() { 7 | utest.UTest.run([ 8 | new TestCase(), 9 | new TestCase2(), 10 | new tests.TestCase(), 11 | new TestCase3(), 12 | new TestCase4() 13 | ]); 14 | } 15 | } 16 | 17 | class TestCase extends utest.Test { 18 | function testSuccess() { 19 | Sys.sleep(Math.random()); 20 | Assert.isTrue(true); 21 | } 22 | 23 | function testFailure() { 24 | Sys.sleep(Math.random()); 25 | Assert.equals("A", "B"); 26 | Assert.isTrue(true); 27 | } 28 | 29 | function testError() { 30 | Sys.sleep(Math.random()); 31 | throw "failure"; 32 | } 33 | 34 | function testEmpty() { 35 | Sys.sleep(Math.random()); 36 | } 37 | 38 | @Ignored("Description") // utest 1.x 39 | @:ignore("Description") // utest 2.x 40 | function testIgnore() {} 41 | } 42 | 43 | class TestCase2 extends utest.Test { 44 | function testSuccess() { 45 | Assert.isTrue(true); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /samples/utest/src/tests/TestCase.hx: -------------------------------------------------------------------------------- 1 | package tests; 2 | 3 | import utest.Assert; 4 | 5 | class TestCase extends utest.Test { 6 | function testSuccess() { 7 | Assert.isTrue(true); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/utest/src/tests/TestCase3.hx: -------------------------------------------------------------------------------- 1 | package tests; 2 | 3 | import utest.Assert; 4 | 5 | class TestCase3 extends utest.Test { 6 | function testSuccess() { 7 | Assert.isTrue(true); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/utest/src/tests/pack/TestCase4.hx: -------------------------------------------------------------------------------- 1 | package tests.pack; 2 | 3 | import utest.Assert; 4 | 5 | class TestCase4 extends utest.Test { 6 | function testSuccess() { 7 | Assert.isTrue(true); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/utest/test.hxml: -------------------------------------------------------------------------------- 1 | -cp src 2 | -lib utest 3 | -x Main -------------------------------------------------------------------------------- /src/HaxeTestController.hx: -------------------------------------------------------------------------------- 1 | import haxe.Json; 2 | import haxe.Timer; 3 | import haxe.ds.ArraySort; 4 | import haxe.io.Path; 5 | import js.lib.Promise; 6 | import sys.FileSystem; 7 | import sys.io.File; 8 | import _testadapter.data.Data; 9 | import _testadapter.data.TestFilter; 10 | import _testadapter.data.TestResults; 11 | import lcov.Report; 12 | import vscode.BranchCoverage; 13 | import vscode.CancellationToken; 14 | import vscode.DebugSession; 15 | import vscode.DeclarationCoverage; 16 | import vscode.ExtensionContext; 17 | import vscode.FileCoverage; 18 | import vscode.FileCoverageDetail; 19 | import vscode.FileSystemWatcher; 20 | import vscode.Location; 21 | import vscode.OutputChannel; 22 | import vscode.Position; 23 | import vscode.ProcessExecution; 24 | import vscode.Range; 25 | import vscode.RelativePattern; 26 | import vscode.StatementCoverage; 27 | import vscode.Task; 28 | import vscode.TaskEndEvent; 29 | import vscode.TaskExecution; 30 | import vscode.TestController; 31 | import vscode.TestCoverageCount; 32 | import vscode.TestItem; 33 | import vscode.TestItemCollection; 34 | import vscode.TestMessage; 35 | import vscode.TestRun; 36 | import vscode.TestRunRequest; 37 | import vscode.Uri; 38 | import vscode.WorkspaceFolder; 39 | 40 | using StringTools; 41 | 42 | typedef TestItemData = { 43 | test:TestMethodResults, 44 | testItem:TestItem, 45 | clazzUri:Uri 46 | } 47 | 48 | class HaxeTestController { 49 | static inline final HAXE_TESTS = "Haxe Tests"; 50 | 51 | final context:ExtensionContext; 52 | final channel:OutputChannel; 53 | final controller:TestController; 54 | final dataWatcher:FileSystemWatcher; 55 | final workspaceFolder:WorkspaceFolder; 56 | var filter:TestFilter; 57 | var suiteResults:TestSuiteResults; 58 | var currentTask:Null; 59 | var currentRun:Null; 60 | var isCoverageRun:Bool; 61 | var delayForCoverageResults:Int; 62 | 63 | public function new(context:ExtensionContext, workspaceFolder:WorkspaceFolder) { 64 | this.context = context; 65 | this.workspaceFolder = workspaceFolder; 66 | 67 | delayForCoverageResults = getWaitForCoverage(); 68 | 69 | channel = Vscode.window.createOutputChannel('${workspaceFolder.name} Tests'); 70 | channel.appendLine('Starting test adapter for ${workspaceFolder.name}'); 71 | 72 | controller = Vscode.tests.createTestController('haxe-test-controller-${workspaceFolder.name}', '${workspaceFolder.name} Tests'); 73 | controller.createRunProfile('Run Tests for ${workspaceFolder.name}', vscode.TestRunProfileKind.Run, runHandler, true); 74 | controller.createRunProfile('Debug Tests for ${workspaceFolder.name}', vscode.TestRunProfileKind.Debug, debugHandler, false); 75 | 76 | if (isCoverageUIEnabled()) { 77 | final coverageProfile = controller.createRunProfile('Run Tests with Coverage for ${workspaceFolder.name}', vscode.TestRunProfileKind.Coverage, 78 | coverageHandler, true); 79 | 80 | coverageProfile.loadDetailedCoverage = loadDetailedCoverage; 81 | coverageProfile.loadDetailedCoverageForTest = loadDetailedCoverageForTest; 82 | } 83 | 84 | var pattern = new RelativePattern(workspaceFolder, "**/" + TestResults.getRelativeFileName()); 85 | dataWatcher = Vscode.workspace.createFileSystemWatcher(pattern); 86 | dataWatcher.onDidCreate(onResultFile); 87 | dataWatcher.onDidChange(onResultFile); 88 | 89 | filter = new TestFilter(workspaceFolder.uri.fsPath); 90 | Vscode.tasks.onDidEndTask(testTaskEnded); 91 | Vscode.debug.onDidTerminateDebugSession(testDebugEnd); 92 | 93 | currentRun = controller.createTestRun(new TestRunRequest(), HAXE_TESTS); 94 | loadFrom(workspaceFolder.uri.path); 95 | } 96 | 97 | function runHandler(request:TestRunRequest, token:CancellationToken):Thenable { 98 | if (currentRun != null) { 99 | return Promise.reject("tests already running"); 100 | } 101 | channel.appendLine("start running Tests"); 102 | token.onCancellationRequested((e) -> cancel()); 103 | 104 | isCoverageRun = false; 105 | currentRun = controller.createTestRun(request, HAXE_TESTS); 106 | setFilters(request); 107 | setAllStarted(controller.items); 108 | 109 | var vshaxe:Vshaxe = Vscode.extensions.getExtension("nadako.vshaxe").exports; 110 | var haxeExecutable = vshaxe.haxeExecutable.configuration; 111 | 112 | var testCommand:Null> = Vscode.workspace.getConfiguration("haxeTestExplorer", workspaceFolder).get("testCommand"); 113 | if (testCommand == null) { 114 | return Promise.reject("please set \"haxeTestExplorer.coverageCommand\" in settings.json"); 115 | } 116 | testCommand = testCommand.map(arg -> if (arg == "${haxe}") haxeExecutable.executable else arg); 117 | 118 | var task = new Task({type: "haxe-test-explorer-run"}, workspaceFolder, "Running Haxe Tests", "haxe", 119 | new ProcessExecution(testCommand.shift(), testCommand, {env: haxeExecutable.env}), cast vshaxe.problemMatchers); 120 | var presentation = vshaxe.taskPresentation; 121 | task.presentationOptions = { 122 | reveal: presentation.reveal, 123 | echo: presentation.echo, 124 | focus: presentation.focus, 125 | panel: presentation.panel, 126 | showReuseMessage: presentation.showReuseMessage, 127 | clear: presentation.clear 128 | }; 129 | 130 | var thenable:Thenable = Vscode.tasks.executeTask(task); 131 | return thenable.then(function(taskExecution:TaskExecution) { 132 | currentTask = taskExecution; 133 | }, taskLaunchError); 134 | } 135 | 136 | function coverageHandler(request:TestRunRequest, token:CancellationToken):Thenable { 137 | if (currentRun != null) { 138 | return Promise.reject("tests already running"); 139 | } 140 | var testCommand:Null> = Vscode.workspace.getConfiguration("haxeTestExplorer", workspaceFolder).get("coverageCommand"); 141 | if (testCommand == null) { 142 | channel.appendLine("please set \"haxeTestExplorer.coverageCommand\" in settings.json"); 143 | return Promise.reject("please set \"haxeTestExplorer.coverageCommand\" in settings.json"); 144 | } 145 | 146 | channel.appendLine("start running Tests (with coveraqge)"); 147 | token.onCancellationRequested((e) -> cancel()); 148 | 149 | isCoverageRun = true; 150 | currentRun = controller.createTestRun(request, HAXE_TESTS); 151 | setFilters(request); 152 | setAllStarted(controller.items); 153 | 154 | var vshaxe:Vshaxe = Vscode.extensions.getExtension("nadako.vshaxe").exports; 155 | var haxeExecutable = vshaxe.haxeExecutable.configuration; 156 | 157 | testCommand = testCommand.map(arg -> if (arg == "${haxe}") haxeExecutable.executable else arg); 158 | if (!isCoverageUIEnabled() || !isAttributableCoverageEnabled()) { 159 | testCommand.push("-D"); 160 | testCommand.push("disable-attributable-coverage"); 161 | } 162 | 163 | var task = new Task({type: "haxe-test-explorer-run"}, workspaceFolder, "Running Haxe Tests with Coverage", "haxe", 164 | new ProcessExecution(testCommand.shift(), testCommand, {env: haxeExecutable.env}), cast vshaxe.problemMatchers); 165 | var presentation = vshaxe.taskPresentation; 166 | task.presentationOptions = { 167 | reveal: presentation.reveal, 168 | echo: presentation.echo, 169 | focus: presentation.focus, 170 | panel: presentation.panel, 171 | showReuseMessage: presentation.showReuseMessage, 172 | clear: presentation.clear 173 | }; 174 | 175 | var thenable:Thenable = Vscode.tasks.executeTask(task); 176 | return thenable.then(function(taskExecution:TaskExecution) { 177 | currentTask = taskExecution; 178 | try { 179 | FileSystem.deleteFile(getInstumentFullCoveragePath()); 180 | } catch (e) { 181 | // ignore delete error 182 | } 183 | }, taskLaunchError); 184 | } 185 | 186 | function debugHandler(request:TestRunRequest, token:CancellationToken):Thenable { 187 | channel.appendLine("start debugging Tests"); 188 | token.onCancellationRequested((e) -> cancel()); 189 | 190 | isCoverageRun = false; 191 | currentRun = controller.createTestRun(request, HAXE_TESTS); 192 | setFilters(request); 193 | setAllStarted(controller.items); 194 | 195 | var launchConfig = Vscode.workspace.getConfiguration("haxeTestExplorer", workspaceFolder).get("launchConfiguration"); 196 | if (launchConfig == null) { 197 | return Promise.reject("please set \"haxeTestExplorer.launchConfiguration\" in settings.json"); 198 | } 199 | var thenable:Thenable = Vscode.debug.startDebugging(workspaceFolder, launchConfig); 200 | return thenable.then(function(b:Bool) {}, taskLaunchError); 201 | } 202 | 203 | function taskLaunchError(error) { 204 | channel.appendLine('Running tests for ${workspaceFolder.name} failed with $error'); 205 | currentRun.appendOutput('Running tests for ${workspaceFolder.name} failed with $error'); 206 | currentRun.end(); 207 | currentRun = null; 208 | } 209 | 210 | function setFilters(request:TestRunRequest) { 211 | var include:Array = []; 212 | var exclude:Array = []; 213 | if (request.include != null) { 214 | include = request.include.map(f -> f.id); 215 | } 216 | if (request.exclude != null) { 217 | exclude = request.exclude.map(f -> f.id); 218 | } 219 | filter.set(include, exclude); 220 | channel.appendLine('include: [${include.join(", ")}] - exclude: [${exclude.join(", ")}]'); 221 | } 222 | 223 | @:access(_testadapter.data.TestFilter) 224 | function setAllStarted(collection:TestItemCollection) { 225 | if (collection == null) { 226 | return; 227 | } 228 | var filters:TestFilterList = filter.testFilters; 229 | collection.forEach((item, col) -> { 230 | setAllStarted(item.children); 231 | if (filters.include.length > 0) { 232 | var found = false; 233 | for (id in filters.include) { 234 | if (id == item.id) { 235 | found = true; 236 | break; 237 | } 238 | if (item.id.startsWith('$id.')) { 239 | found = true; 240 | break; 241 | } 242 | } 243 | if (!found) { 244 | return null; 245 | } 246 | } 247 | if (filters.exclude.contains(item.id)) { 248 | return null; 249 | } 250 | currentRun.started(item); 251 | return null; 252 | }); 253 | } 254 | 255 | function testTaskEnded(event:TaskEndEvent) { 256 | if ((currentTask == null) || Json.stringify(event.execution.task.definition) != Json.stringify(currentTask.task.definition)) { 257 | return; 258 | } 259 | loadFrom(workspaceFolder.uri.path); 260 | channel.appendLine('Running tests for ${workspaceFolder.name} finished'); 261 | currentTask = null; 262 | } 263 | 264 | function testDebugEnd(session:DebugSession) { 265 | if (currentRun != null) { 266 | channel.appendLine('Debugging tests for ${workspaceFolder.name} finished'); 267 | currentRun.end(); 268 | } 269 | currentRun = null; 270 | currentTask = null; 271 | } 272 | 273 | function cancel() { 274 | if (currentRun != null) { 275 | currentRun.end(); 276 | } 277 | currentRun = null; 278 | channel.appendLine('Test run for ${workspaceFolder.name} cancelled'); 279 | Vscode.debug.stopDebugging(); 280 | if (currentTask != null) { 281 | currentTask.terminate(); 282 | } 283 | currentTask = null; 284 | } 285 | 286 | function onResultFile(uri:Uri) { 287 | if (currentRun == null) { 288 | currentRun = controller.createTestRun(new TestRunRequest(), HAXE_TESTS); 289 | } 290 | var unitTestFolder = Path.directory(uri.fsPath); 291 | var baseFolder = Path.directory(unitTestFolder); 292 | if (isCoverageRun) { 293 | Timer.delay(() -> loadFrom(baseFolder), delayForCoverageResults); 294 | } else { 295 | loadFrom(baseFolder); 296 | } 297 | } 298 | 299 | function loadFrom(baseFolder:String) { 300 | if (currentRun == null) { 301 | return; 302 | } 303 | filter = new TestFilter(baseFolder); 304 | suiteResults = TestResults.load(baseFolder); 305 | if (suiteResults == null) { 306 | currentRun.appendOutput("No tests results found!"); 307 | currentRun.end(); 308 | currentRun = null; 309 | return; 310 | } 311 | 312 | parseSuiteData(baseFolder, suiteResults); 313 | currentRun.appendOutput("Loaded tests results"); 314 | currentRun.end(); 315 | currentRun = null; 316 | channel.appendLine("Loaded tests results"); 317 | } 318 | 319 | function makeFileName(baseFolder:String, file:String):String { 320 | var fileName:String = Path.join([baseFolder, file]); 321 | // it seems Test Explorer UI wants backslashes on Windows 322 | if (Sys.systemName() == "Windows") { 323 | fileName = fileName.replace("/", "\\"); 324 | } 325 | return fileName; 326 | } 327 | 328 | function parseSuiteData(baseFolder:String, testSuiteResults:TestSuiteResults) { 329 | var key:String = testSuiteResults.name + ":" + workspaceFolder.name; 330 | var root:TestItem = controller.items.get(key); 331 | if (root == null) { 332 | root = controller.createTestItem(key, workspaceFolder.name); 333 | controller.items.add(root); 334 | } 335 | 336 | function sortByLine(a:{line:Null}, b:{line:Null}) { 337 | if (a.line == null || b.line == null) { 338 | return 0; 339 | } 340 | return a.line - b.line; 341 | } 342 | 343 | var classes = testSuiteResults.classes; 344 | ArraySort.sort(classes, (a, b) -> { 345 | if (a.pos == null || b.pos == null) { 346 | return 0; 347 | } 348 | if (a.pos.file != b.pos.file) { 349 | return Reflect.compare(a.pos.file, b.pos.file); 350 | } 351 | return sortByLine(a.pos, b.pos); 352 | }); 353 | 354 | var testItems:Array = []; 355 | for (clazz in classes) { 356 | var clazzUri:Uri = Uri.file(makeFileName(baseFolder, clazz.pos.file)); 357 | var classItem:TestItem = controller.createTestItem(clazz.id, clazz.name, clazzUri); 358 | 359 | if (clazz.pos != null && clazz.pos.file != null && clazz.pos.line != null && clazz.pos.line != 0) { 360 | classItem.range = new Range(clazz.pos.line, 0, clazz.pos.line, 0); 361 | } 362 | ArraySort.sort(clazz.methods, sortByLine); 363 | for (test in clazz.methods) { 364 | var testItem:TestItem = controller.createTestItem(clazz.id + "." + test.name, test.name, clazzUri); 365 | if (clazz.pos != null && test.line != null && clazz.pos.file != null) { 366 | testItem.range = new Range(test.line, 0, test.line, 0); 367 | } 368 | classItem.children.add(testItem); 369 | testItems.push({ 370 | test: test, 371 | testItem: testItem, 372 | clazzUri: clazzUri 373 | }); 374 | } 375 | insertTestSuite(root, classItem); 376 | } 377 | for (item in testItems) { 378 | updateTestState(item.test, item.testItem, item.clazzUri); 379 | } 380 | final currentTestItems = testItems.map(f -> f.testItem); 381 | if (isCoverageUIEnabled() && isCoverageRun) { 382 | updateTestCoverage(currentTestItems); 383 | } 384 | } 385 | 386 | function insertTestSuite(root:TestItem, newItem:TestItem) { 387 | var pack:Array = newItem.label.split("."); 388 | var id:Null = null; 389 | var label:Null = pack.pop(); 390 | if (label == null) { 391 | root.children.add(newItem); 392 | return; 393 | } 394 | newItem.label = label; 395 | for (p in pack) { 396 | var found:Bool = false; 397 | root.children.forEach((child, collection) -> { 398 | if (found) { 399 | return null; 400 | } 401 | if (child.label == p) { 402 | root = child; 403 | found = true; 404 | } 405 | return null; 406 | }); 407 | if (id == null) { 408 | id = p; 409 | } else { 410 | id += '.$p'; 411 | } 412 | if (!found) { 413 | var packItem:TestItem = controller.createTestItem(id, p); 414 | root.children.add(packItem); 415 | root = packItem; 416 | } 417 | } 418 | root.children.add(newItem); 419 | } 420 | 421 | function updateTestState(test:TestMethodResults, testItem:TestItem, clazzUri:Uri) { 422 | switch (test.state) { 423 | case Success: 424 | if (test.executionTime == null) { 425 | currentRun.passed(testItem); 426 | } else { 427 | currentRun.passed(testItem, test.executionTime); 428 | } 429 | case Failure: 430 | var msg = buildFailureMessage(test); 431 | var line:Int = test.line; 432 | if (test.errorPos != null) { 433 | line = test.errorPos.line; 434 | clazzUri = Uri.file(makeFileName(workspaceFolder.uri.path, test.errorPos.file)); 435 | } 436 | msg.location = new Location(clazzUri, new Range(line, 0, line + 1, 0)); 437 | if (test.executionTime == null) { 438 | currentRun.failed(testItem, msg); 439 | } else { 440 | currentRun.failed(testItem, msg, test.executionTime); 441 | } 442 | case Error: 443 | var msg:TestMessage = new TestMessage(test.message); 444 | msg.location = new Location(clazzUri, new Range(test.line, 0, test.line + 1, 0)); 445 | if (test.executionTime == null) { 446 | currentRun.errored(testItem, msg); 447 | } else { 448 | currentRun.errored(testItem, msg, test.executionTime); 449 | } 450 | case Ignore: 451 | currentRun.skipped(testItem); 452 | } 453 | } 454 | 455 | function buildFailureMessage(test:TestMethodResults):TestMessage { 456 | var msg:TestMessage = new TestMessage(test.message); 457 | // utest diff format 458 | var reg:EReg = ~/^expected "(.*)" but it is "(.*)"$/s; 459 | if (reg.match(test.message)) { 460 | msg = TestMessage.diff(test.message, reg.matched(1), reg.matched(2)); 461 | } 462 | reg = ~/^expected (.*) but it is (.*)$/s; 463 | if (reg.match(test.message)) { 464 | msg = TestMessage.diff(test.message, reg.matched(1), reg.matched(2)); 465 | } 466 | // munit diff format 467 | reg = ~/^Value \[(.*)\] was not equal to expected value \[(.*)\]$/s; 468 | if (reg.match(test.message)) { 469 | msg = TestMessage.diff(test.message, reg.matched(2), reg.matched(1)); 470 | } 471 | // buddy diff format 472 | reg = ~/^Expected "(.*)", was "(.*)"$/s; 473 | if (reg.match(test.message)) { 474 | msg = TestMessage.diff(test.message, reg.matched(1), reg.matched(2)); 475 | } 476 | // haxeunit + hexunit diff format 477 | reg = ~/[eE]xpected '(.*)' but was '(.*)'$/s; 478 | if (reg.match(test.message)) { 479 | msg = TestMessage.diff(test.message, reg.matched(1), reg.matched(2)); 480 | } 481 | return msg; 482 | } 483 | 484 | function updateTestCoverage(currentTestItems:Array) { 485 | if (currentRun == null) { 486 | return; 487 | } 488 | if (currentTestItems.length <= 0) { 489 | return; 490 | } 491 | channel.appendLine("updating test coverage"); 492 | 493 | var filteredTestItems:Null> = null; 494 | if (isAttributableCoverageEnabled()) { 495 | filteredTestItems = []; 496 | for (item in currentTestItems) { 497 | var fileName:LCOVFileName = '${item.id}.lcov'; 498 | final lcovFilename = makeFileName(workspaceFolder.uri.path, Path.join([Data.FOLDER, fileName])); 499 | 500 | if (FileSystem.exists(lcovFilename)) { 501 | filteredTestItems.push(item); 502 | } 503 | } 504 | if (filteredTestItems.length <= 0) { 505 | filteredTestItems = null; 506 | } 507 | } 508 | updateCoverageView(filteredTestItems, getFullCoveragePath()); 509 | } 510 | 511 | function updateCoverageView(filteredTestItems:Null>, lcovPath:String) { 512 | if (!FileSystem.exists(lcovPath)) { 513 | return; 514 | } 515 | switch (Report.parse(File.getContent(lcovPath))) { 516 | case Failure(failure): 517 | channel.appendLine("failed to parse LCOV data: " + failure); 518 | case Success(data): 519 | for (file in data.sourceFiles) { 520 | var statementCoverage:TestCoverageCount = new TestCoverageCount(file.lines.hit, file.lines.found); 521 | var branchCoverage:TestCoverageCount = new TestCoverageCount(file.branches.hit, file.branches.found); 522 | var functionCoverage:TestCoverageCount = new TestCoverageCount(file.functions.hit, file.functions.found); 523 | var fileName = if (file.path.startsWith(workspaceFolder.uri.path)) { 524 | makeFileName(null, file.path); 525 | } else { 526 | makeFileName(workspaceFolder.uri.path, file.path); 527 | }; 528 | 529 | if (filteredTestItems == null) { 530 | currentRun.addCoverage(new FileCoverage(Uri.parse(fileName), statementCoverage, branchCoverage, functionCoverage)); 531 | } else { 532 | currentRun.addCoverage(new FileCoverage(Uri.parse(fileName), statementCoverage, branchCoverage, functionCoverage, filteredTestItems)); 533 | } 534 | } 535 | } 536 | } 537 | 538 | function loadDetailedCoverage(testRun:TestRun, fileCoverage:FileCoverage, token:CancellationToken):Thenable> { 539 | return reportDetailedCoverage(getFullCoveragePath(), fileCoverage.uri.fsPath); 540 | } 541 | 542 | function loadDetailedCoverageForTest(testRun:TestRun, fileCoverage:FileCoverage, fromTestItem:TestItem, 543 | token:CancellationToken):Thenable> { 544 | var fileName:LCOVFileName = '${fromTestItem.id}.lcov'; 545 | final lcovFilename = makeFileName(workspaceFolder.uri.path, Path.join([Data.FOLDER, fileName])); 546 | return reportDetailedCoverage(lcovFilename, fileCoverage.uri.fsPath); 547 | } 548 | 549 | function reportDetailedCoverage(lcovFileName:String, srcFileName:String):Thenable> { 550 | var details:Array = []; 551 | 552 | if (!FileSystem.exists(lcovFileName)) { 553 | return Promise.reject("no coverage data found"); 554 | } 555 | switch (Report.parse(File.getContent(lcovFileName))) { 556 | case Failure(failure): 557 | return Promise.reject(failure); 558 | case Success(data): 559 | for (file in data.sourceFiles) { 560 | var fileName = if (file.path.startsWith(workspaceFolder.uri.path)) { 561 | makeFileName(null, file.path); 562 | } else { 563 | makeFileName(workspaceFolder.uri.path, file.path); 564 | }; 565 | if (fileName != srcFileName) { 566 | continue; 567 | } 568 | 569 | for (func in file.functions.data) { 570 | final coverageDetail = new DeclarationCoverage(func.functionName, func.executionCount > 0 ? func.executionCount : false, 571 | new Position(func.lineNumber - 1, 0)); 572 | details.push(coverageDetail); 573 | } 574 | var branches:Array = []; 575 | var block:Int = -1; 576 | for (branch in file.branches.data) { 577 | if (branch.blockNumber != block) { 578 | block = branch.blockNumber; 579 | branches = []; 580 | final coverageDetail = new StatementCoverage(branch.taken > 0 ? branch.taken : false, new Position(branch.lineNumber - 1, 0), 581 | branches); 582 | details.push(coverageDetail); 583 | } 584 | branches.push(new BranchCoverage(branch.taken > 0 ? branch.taken : false, new Position(branch.lineNumber - 1, 0))); 585 | } 586 | for (line in file.lines.data) { 587 | final coverageDetail = new StatementCoverage(line.executionCount > 0 ? line.executionCount : false, 588 | new Position(line.lineNumber - 1, 0)); 589 | details.push(coverageDetail); 590 | } 591 | } 592 | } 593 | 594 | return Promise.resolve(details); 595 | } 596 | 597 | function isCoverageUIEnabled():Bool { 598 | var coverageUIEnabled:Null = Vscode.workspace.getConfiguration("haxeTestExplorer", workspaceFolder).get("enableCoverageUI"); 599 | if (coverageUIEnabled == null) { 600 | return true; 601 | } 602 | return coverageUIEnabled; 603 | } 604 | 605 | function isAttributableCoverageEnabled():Bool { 606 | var attributableCoverageEnabled:Null = Vscode.workspace.getConfiguration("haxeTestExplorer", workspaceFolder).get("enableAttributableCoverage"); 607 | if (attributableCoverageEnabled == null) { 608 | return true; 609 | } 610 | return attributableCoverageEnabled; 611 | } 612 | 613 | function getWaitForCoverage():Int { 614 | var waitForCoverage:Null = Vscode.workspace.getConfiguration("haxeTestExplorer", workspaceFolder).get("waitForCoverage"); 615 | if (waitForCoverage == null) { 616 | return 2000; 617 | } 618 | return waitForCoverage; 619 | } 620 | 621 | function getFullCoveragePath():String { 622 | final path = getInstumentFullCoveragePath(); 623 | if (FileSystem.exists(path)) { 624 | return path; 625 | } 626 | var lcovPath:Null = Vscode.workspace.getConfiguration("haxeTestExplorer", workspaceFolder).get("lcovPath"); 627 | if (lcovPath == null) { 628 | lcovPath = "lcov.info"; 629 | } 630 | return makeFileName(workspaceFolder.uri.path, lcovPath); 631 | } 632 | 633 | function getInstumentFullCoveragePath():String { 634 | return makeFileName(workspaceFolder.uri.path, Path.join([Data.FOLDER, "lcov.info"])); 635 | } 636 | 637 | static function updateHaxelib(context:ExtensionContext) { 638 | Vscode.commands.registerCommand("haxeTestExplorer.setup", function() { 639 | var terminal = Vscode.window.createTerminal(); 640 | terminal.sendText("haxelib dev test-adapter \"" + context.asAbsolutePath("test-adapter") + "\""); 641 | terminal.show(); 642 | context.globalState.update("previousExtensionPath", context.extensionPath); 643 | }); 644 | 645 | if (isExtensionPathChanged(context)) { 646 | Vscode.commands.executeCommand("haxeTestExplorer.setup"); 647 | } 648 | } 649 | 650 | static function isExtensionPathChanged(context:ExtensionContext):Bool { 651 | var previousPath = context.globalState.get("previousExtensionPath"); 652 | return (context.extensionPath != previousPath); 653 | } 654 | 655 | @:expose("activate") 656 | static function main(context:ExtensionContext) { 657 | for (folder in Vscode.workspace.workspaceFolders) { 658 | new HaxeTestController(context, folder); 659 | } 660 | updateHaxelib(context); 661 | } 662 | } 663 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/Macro.hx: -------------------------------------------------------------------------------- 1 | package _testadapter; 2 | 3 | import haxe.macro.Compiler; 4 | import haxe.macro.Context; 5 | import haxe.macro.Expr; 6 | import haxe.macro.PositionTools; 7 | import haxe.macro.Type; 8 | import _testadapter.data.TestFilter; 9 | import _testadapter.data.TestPositions; 10 | 11 | using Lambda; 12 | using StringTools; 13 | 14 | #if (haxe_ver >= 4) 15 | import haxe.display.Position.Location; 16 | #end 17 | 18 | class Macro { 19 | #if macro 20 | static var positions = new TestPositions(Sys.getCwd(), new Positions()); 21 | public static var filters(default, null):TestFilterList; 22 | 23 | static function require(lib:String, minVersion:String) { 24 | var version = Context.definedValue(lib); 25 | if (version == null) { 26 | return; 27 | } 28 | var a = version.split(".").map(Std.parseInt); 29 | var b = minVersion.split(".").map(Std.parseInt); 30 | if (a[0] > b[0]) { 31 | return; 32 | } 33 | if (a[0] == b[0]) { 34 | if (a[1] > b[1]) { 35 | return; 36 | } 37 | if ((a[1] == b[1]) && (a[2] >= b[2])) { 38 | return; 39 | } 40 | } 41 | Context.fatalError('test-adapter requires $lib $minVersion or newer, found $version', Context.currentPos()); 42 | } 43 | 44 | public static function init() { 45 | if (Context.defined("display")) { 46 | return; 47 | } 48 | 49 | require("munit", "2.3.2"); 50 | require("utest", "1.13.0"); 51 | require("buddy", "2.10.0"); 52 | require("hexunit", "0.35.0"); 53 | require("tink_testrunner", "0.8.0"); 54 | 55 | require("instrument", "1.3.1"); 56 | 57 | setupHooks(); 58 | 59 | var testFilter = new TestFilter(Sys.getCwd()); 60 | filters = { 61 | include: testFilter.get().include, 62 | exclude: testFilter.get().exclude 63 | }; 64 | testFilter.clear(); 65 | 66 | Context.onGenerate(function(_) { 67 | // no side effects for caching, only actual builds 68 | if (Sys.args().indexOf("--no-output") == -1) { 69 | Sys.println("test-adapter is recording results...\n"); 70 | positions.save(); 71 | } 72 | }); 73 | } 74 | 75 | static function setupHooks() { 76 | inline function build(func:String, target:String) { 77 | Compiler.addGlobalMetadata(target, '@:build(_testadapter.$func)', false); 78 | } 79 | inline function autoBuild(func:String, target:String) { 80 | Compiler.addGlobalMetadata(target, '@:autoBuild(_testadapter.$func)', false); 81 | } 82 | 83 | // record positions / line numbers 84 | #if (munit || hexunit || tink_testrunner) 85 | Compiler.addGlobalMetadata("", "@:build(_testadapter.Macro.recordPositions(true))", true, true, false); 86 | #end 87 | 88 | // munit 89 | build("munit.Injector.buildRunner()", "massive.munit.TestRunner"); 90 | build("munit.Injector.buildHelper()", "massive.munit.TestClassHelper"); 91 | 92 | // utest 93 | autoBuild("Macro.recordPositions(false)", "utest.ITest"); 94 | build("utest.Injector.build()", "utest.Runner"); 95 | 96 | // buddy 97 | autoBuild("Macro.recordPositions(false)", "buddy.BuddySuite"); 98 | build("buddy.Injector.buildSuite()", "buddy.BuddySuite"); 99 | build("buddy.Injector.buildRunner()", "buddy.SuitesRunner"); 100 | 101 | // hexUnit 102 | build("hexunit.Injector.buildCore()", "hex.unittest.runner.ExMachinaUnitCore"); 103 | 104 | // tink_unittest 105 | build("tink_unittest.Injector.buildRunner()", "tink.testrunner.Runner"); 106 | 107 | // haxe.unit 108 | autoBuild("Macro.recordPositions(false)", "haxe.unit.TestCase"); 109 | autoBuild("haxeunit.Injector.buildCase()", "haxe.unit.TestCase"); 110 | build("haxeunit.Injector.buildRunner()", "haxe.unit.TestRunner"); 111 | 112 | // instrument attributable coverage 113 | build("instrument.Injector.buildCoverage()", "instrument.coverage.Coverage"); 114 | } 115 | 116 | public static function recordPositions(applyClassNameFilter:Bool):Null> { 117 | var ref:Ref = Context.getLocalClass(); 118 | if (ref == null) { 119 | return null; 120 | } 121 | var cls:ClassType = ref.get(); 122 | if (cls.isInterface || cls.name == null || cls.kind.match(KAbstractImpl(_))) { 123 | return null; 124 | } 125 | 126 | var dotPath = cls.pack.join("."); 127 | var ignoredPackages = [ 128 | "_testadapter", 129 | "massive.munit", 130 | "utest", 131 | "buddy", 132 | "hex.unittest", 133 | "haxe.unit", 134 | "tink.unit" 135 | ]; 136 | for (ignoredPackage in ignoredPackages) { 137 | if (dotPath.startsWith(ignoredPackage)) { 138 | return null; 139 | } 140 | } 141 | 142 | if (applyClassNameFilter) { 143 | var filter = Context.definedValue("test-adapter-filter"); 144 | var regex = if (filter == null) ~/Test/ else new EReg(filter, ""); 145 | 146 | var hierarchyNames = []; 147 | function loop(c:ClassType) { 148 | hierarchyNames.push(c.name); 149 | c.interfaces.iter(function(r) loop(r.t.get())); 150 | if (c.superClass != null) { 151 | loop(c.superClass.t.get()); 152 | } 153 | } 154 | loop(cls); 155 | if (!hierarchyNames.exists(regex.match)) { 156 | return null; 157 | } 158 | } 159 | 160 | var className = makeLocation(cls.name); 161 | addTestPos(className, cls.pos); 162 | for (field in Context.getBuildFields()) { 163 | if (field.name == "new" || field.name.startsWith("__")) { 164 | continue; 165 | } 166 | addTestPos(className, field.name, field.pos); 167 | } 168 | return null; 169 | } 170 | 171 | static function makeLocation(clazz:String):String { 172 | var location:String = Context.getLocalModule(); 173 | if (location == clazz) { 174 | return location; 175 | } 176 | if (location.endsWith('.$clazz')) { 177 | return location; 178 | } 179 | var parts:Array = location.split("."); 180 | parts.pop(); 181 | parts.push(clazz); 182 | return parts.join("."); 183 | } 184 | 185 | static function addTestPos(className:String, ?testName:String, pos:Position) { 186 | #if (haxe_ver >= 4) 187 | var location:Location = PositionTools.toLocation(pos); 188 | var fileName:String = cast location.file; 189 | if (fileName == "?") { 190 | return; 191 | } 192 | positions.add(className, testName, { 193 | file: fileName, 194 | line: location.range.start.line - 1 195 | }); 196 | #else 197 | var posInfo = Context.getPosInfos(pos); 198 | if (posInfo.file == "?") { 199 | return; 200 | } 201 | // TODO line numbers for Haxe 3 compile 202 | positions.add(className, testName, { 203 | file: posInfo.file, 204 | line: null 205 | }); 206 | #end 207 | } 208 | #end 209 | } 210 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/PatchTools.hx: -------------------------------------------------------------------------------- 1 | package _testadapter; 2 | 3 | #if macro 4 | import haxe.macro.Expr; 5 | import haxe.macro.Expr.Field; 6 | import _testadapter.Macro; 7 | 8 | class PatchTools { 9 | public static function patch(field:Field, kind:PatchKind, expr:Expr) { 10 | switch (field.kind) { 11 | case FFun(f): 12 | switch (f.expr.expr) { 13 | case EBlock(exprs): 14 | switch (kind) { 15 | case Start: 16 | exprs.unshift(expr); 17 | case End: 18 | exprs.push(expr); 19 | case Replace: 20 | f.expr = expr; 21 | } 22 | case _: 23 | } 24 | case _: 25 | } 26 | } 27 | 28 | public static function addInit(field:Field, ?kind:PatchKind, init:Expr) { 29 | if (kind == null) { 30 | kind = End; 31 | } 32 | patch(field, kind, macro { 33 | if (!_testadapter.data.TestFilter.hasFilters($v{Macro.filters})) { 34 | _testadapter.data.TestResults.clear($v{Sys.getCwd()}); 35 | } 36 | $init; 37 | }); 38 | } 39 | } 40 | 41 | enum PatchKind { 42 | Start; 43 | End; 44 | Replace; 45 | } 46 | #end 47 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/buddy/Injector.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.buddy; 2 | 3 | #if macro 4 | import haxe.macro.Context; 5 | import haxe.macro.Expr; 6 | 7 | using haxe.macro.ExprTools; 8 | using _testadapter.PatchTools; 9 | 10 | class Injector { 11 | public static function buildRunner():Array { 12 | var coverageEnabled:Null = Context.definedValue("instrument-coverage"); 13 | var baseFolder = haxe.io.Path.join([_testadapter.data.Data.FOLDER]); 14 | #if disable_attributable_coverage 15 | coverageEnabled = null; 16 | #end 17 | var fields = Context.getBuildFields(); 18 | for (field in fields) { 19 | switch (field.name) { 20 | case "new": 21 | field.addInit(macro { 22 | adapterReporter = new _testadapter.buddy.Reporter($v{Sys.getCwd()}, reporter); 23 | this.reporter = adapterReporter; 24 | }); 25 | case "mapTestSpec" if (coverageEnabled != null): 26 | field.patch(Start, macro switch (testSpec) { 27 | case It(description, _, _, pos, _): 28 | var suiteId:_testadapter.data.Data.SuiteId = SuiteNameAndPos(testSuite.description, pos.fileName, pos.lineNumber); 29 | adapterReporter.addPosition(suiteId, description, pos.fileName, pos.lineNumber - 1); 30 | 31 | // create shallow copies of both before+after arrays 32 | // so we don't mess up the data structures outside of our small patch 33 | var prefix:String = BuddySuite.fullDescribePath(buddySuite.suite, testSuite); 34 | if (prefix == null) { 35 | prefix = ""; 36 | } 37 | var suiteId:_testadapter.data.Data.SuiteId = SuiteNameAndFile(prefix + testSuite.description, pos.fileName); 38 | beforeEachStack = beforeEachStack.copy(); 39 | beforeEachStack.unshift([Sync(() -> instrument.coverage.Coverage.resetAttributableCoverage())]); 40 | afterEachStack = afterEachStack.copy(); 41 | var testCaseName:_testadapter.data.Data.LCOVFileName = '${suiteId}.$description.lcov'; 42 | var path = haxe.io.Path.join([$v{baseFolder}, testCaseName]); 43 | var lcovReporter = new instrument.coverage.reporter.LcovCoverageReporter(path); 44 | afterEachStack.unshift([ 45 | Sync(() -> instrument.coverage.Coverage.reportAttributableCoverage([lcovReporter])) 46 | ]); 47 | case _: 48 | }); 49 | switch (field.kind) { 50 | case FFun(f): 51 | replaceSpec(f.expr); 52 | case _: 53 | } 54 | case "mapTestSpec": 55 | field.patch(Start, macro switch (testSpec) { 56 | case It(description, _, _, pos, _): 57 | var suiteId:_testadapter.data.Data.SuiteId = SuiteNameAndPos(testSuite.description, pos.fileName, pos.lineNumber); 58 | adapterReporter.addPosition(suiteId, description, pos.fileName, pos.lineNumber - 1); 59 | case _: 60 | }); 61 | switch (field.kind) { 62 | case FFun(f): 63 | replaceSpec(f.expr); 64 | case _: 65 | } 66 | case _: 67 | } 68 | } 69 | 70 | var extraFields = (macro class { 71 | var adapterReporter:_testadapter.buddy.Reporter; 72 | }).fields; 73 | return fields.concat(extraFields); 74 | } 75 | 76 | public static function buildSuite():Array { 77 | var fields = Context.getBuildFields(); 78 | for (field in fields) { 79 | if (field.name == "it" || field.name == "xit") { 80 | field.patch(Start, macro { 81 | var prefix:String = BuddySuite.fullDescribePath(suite, currentSuite); 82 | if (prefix == null) { 83 | prefix = ""; 84 | } 85 | var suiteId:_testadapter.data.Data.SuiteId = SuiteNameAndFile(prefix + currentSuite.description, pos.fileName); 86 | if (!_testadapter.data.TestFilter.shouldRunTest($v{Macro.filters}, suiteId, desc) 87 | && !_testadapter.data.TestFilter.shouldRunTest($v{Macro.filters}, suiteId, desc + _testadapter.buddy.Reporter.PENDING_POSTFIX)) { 88 | return; 89 | } 90 | }); 91 | } 92 | } 93 | 94 | var extraFields = (macro class { 95 | public static function fullDescribePath(root:TestSuite, search:TestSuite):Null { 96 | for (childSpec in root.specs) { 97 | switch (childSpec) { 98 | case Describe(child, _): 99 | if (child == search) { 100 | if (root.description.length <= 0) { 101 | return root.description; 102 | } else { 103 | return root.description + "."; 104 | } 105 | } 106 | var path:Null = fullDescribePath(child, search); 107 | if (path != null) { 108 | var prefix:String = root.description; 109 | if (prefix.length > 0) { 110 | prefix += "."; 111 | } 112 | return prefix + path; 113 | } 114 | case _: 115 | } 116 | } 117 | return null; 118 | } 119 | }).fields; 120 | 121 | return fields.concat(extraFields); 122 | } 123 | 124 | static function replaceSpec(func:Expr):Expr { 125 | switch (func.expr) { 126 | case EBinop(OpAssign, e1, e2): 127 | switch (e2.expr) { 128 | case ENew(t, params): 129 | if (t.name == "Spec") { 130 | e2.expr = (macro new _testadapter.buddy.Spec(desc, pos)).expr; 131 | } 132 | case _: 133 | func.map(replaceSpec); 134 | } 135 | return null; 136 | case _: 137 | func.map(replaceSpec); 138 | } 139 | return null; 140 | } 141 | } 142 | #end 143 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/buddy/Reporter.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.buddy; 2 | 3 | import buddy.BuddySuite.Spec; 4 | import buddy.BuddySuite.Step; 5 | import buddy.BuddySuite.Suite; 6 | import buddy.reporting.ConsoleReporter; 7 | import _testadapter.data.Data; 8 | import _testadapter.data.TestResults; 9 | 10 | class Reporter implements buddy.reporting.Reporter { 11 | var testResults:TestResults; 12 | var baseReporter:buddy.reporting.Reporter; 13 | 14 | public static var PENDING_POSTFIX = " (PENDING)"; 15 | 16 | public function new(baseFolder:String, baseReporter:buddy.reporting.Reporter) { 17 | testResults = new TestResults(baseFolder); 18 | if (baseReporter == null) { 19 | baseReporter = new ConsoleReporter(); 20 | } 21 | this.baseReporter = baseReporter; 22 | } 23 | 24 | public function addPosition(suiteName, description:String, fileName:String, lineNumber:Int) { 25 | var pos:Pos = {file: fileName, line: lineNumber}; 26 | testResults.positions.add(suiteName, description, pos); 27 | } 28 | 29 | public function start() { 30 | return baseReporter.start(); 31 | } 32 | 33 | public function progress(spec:Spec) { 34 | return baseReporter.progress(spec); 35 | } 36 | 37 | public function done(suites:Iterable, status:Bool) { 38 | var duplicateNames:Map = new Map(); 39 | function uniqueSuiteName(suiteName:String):String { 40 | if (duplicateNames.exists(suiteName)) { 41 | var count:Int = duplicateNames.get(suiteName); 42 | count++; 43 | duplicateNames.set(suiteName, count); 44 | suiteName = '$suiteName <$count>'; 45 | } else { 46 | duplicateNames.set(suiteName, 1); 47 | } 48 | return suiteName; 49 | } 50 | 51 | function iterateSteps(suiteName:String, steps:Array) { 52 | for (step in steps) { 53 | switch step { 54 | case TSpec(spec): 55 | reportSpec(suiteName, spec); 56 | case TSuite(s): 57 | if (suiteName == "") { 58 | iterateSteps(uniqueSuiteName(s.description), s.steps); 59 | } else { 60 | iterateSteps(uniqueSuiteName(suiteName + "." + s.description), s.steps); 61 | } 62 | } 63 | } 64 | } 65 | for (suite in suites) { 66 | iterateSteps("", suite.steps); 67 | } 68 | 69 | testResults.save(); 70 | return baseReporter.done(suites, status); 71 | } 72 | 73 | function reportSpec(suiteName:String, spec:Spec) { 74 | var testSpec:_testadapter.buddy.Spec = cast spec; 75 | var suiteId:SuiteId = SuiteNameAndFile(suiteName, spec.fileName); 76 | var testId:TestIdentifier = TestNameAndPos(spec.description, spec.fileName, testSpec.pos.lineNumber - 1); 77 | switch (spec.status) { 78 | case Failed: 79 | var message:String = ""; 80 | var lineNumber:Null = null; 81 | var fileName:Null = null; 82 | for (failure in spec.failures) { 83 | message = failure.error; 84 | for (s in failure.stack) { 85 | switch (s) { 86 | case FilePos(_, file, line): 87 | fileName = file; 88 | if (lineNumber == null) { 89 | lineNumber = line - 1; 90 | } 91 | if (line < lineNumber) { 92 | lineNumber = line - 1; 93 | } 94 | case(_): 95 | } 96 | } 97 | } 98 | testResults.add(suiteId, testId, spec.time * 1000, Failure, message, {line: lineNumber, file: fileName}); 99 | case Passed: 100 | testResults.add(suiteId, testId, spec.time * 1000, Success); 101 | case Pending: 102 | testId = TestNameAndPos(spec.description + PENDING_POSTFIX, spec.fileName, testSpec.pos.lineNumber - 1); 103 | testResults.add(suiteId, testId, spec.time * 1000, Ignore); 104 | case Unknown: 105 | testResults.add(suiteId, testId, spec.time * 1000, Error); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/buddy/Spec.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.buddy; 2 | 3 | import haxe.PosInfos; 4 | 5 | class Spec extends buddy.BuddySuite.Spec { 6 | public var pos:PosInfos; 7 | 8 | public function new(description:String, pos:PosInfos) { 9 | this.pos = pos; 10 | super(description, pos.fileName); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/data/Data.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.data; 2 | 3 | import haxe.Json; 4 | import haxe.io.Path; 5 | #if (sys || hxnodejs) 6 | import sys.FileSystem; 7 | import sys.io.File; 8 | #end 9 | 10 | class Data { 11 | public static inline var FOLDER = ".unittest"; 12 | 13 | public static function save(path:String, content:Any) { 14 | #if (sys || hxnodejs) 15 | var directory = Path.directory(path); 16 | if (!FileSystem.exists(directory)) { 17 | FileSystem.createDirectory(directory); 18 | } 19 | File.saveContent(path, Json.stringify(content, "\t")); 20 | #end 21 | } 22 | 23 | public static function clear(path:String) { 24 | #if (sys || hxnodejs) 25 | if (FileSystem.exists(path)) { 26 | FileSystem.deleteFile(path); 27 | } 28 | #end 29 | } 30 | } 31 | 32 | typedef TestSuiteResults = { 33 | var name:String; 34 | var classes:Array; 35 | } 36 | 37 | typedef TestClassResults = { 38 | var id:String; 39 | var name:String; 40 | var methods:Array; 41 | @:optional var pos:Pos; 42 | } 43 | 44 | typedef TestMethodResults = { 45 | var name:String; 46 | var state:TestState; 47 | var message:String; 48 | var timestamp:Float; 49 | @:optional var executionTime:Null; 50 | @:optional var line:Int; 51 | @:optional var errorPos:Pos; 52 | } 53 | 54 | #if haxe4 55 | enum abstract TestState(String) { 56 | var Success = "success"; 57 | var Failure = "failure"; 58 | var Error = "error"; 59 | var Ignore = "ignore"; 60 | } 61 | #else 62 | @:enum abstract TestState(String) { 63 | var Success = "success"; 64 | var Failure = "failure"; 65 | var Error = "error"; 66 | var Ignore = "ignore"; 67 | } 68 | #end 69 | 70 | typedef Pos = { 71 | var file:String; 72 | var line:Int; 73 | } 74 | 75 | enum SuiteIdentifier { 76 | ClassName(className:String); 77 | SuiteNameAndPos(name:String, fileName:String, lineNumber:Int); 78 | SuiteNameAndFile(name:String, fileName:String); 79 | } 80 | 81 | enum TestIdentifier { 82 | TestName(name:String); 83 | TestNameAndPos(name:String, fileName:String, lineNumber:Int); 84 | } 85 | 86 | abstract SuiteId(SuiteIdentifier) from SuiteIdentifier to SuiteIdentifier { 87 | @:to 88 | public function toString():String { 89 | #if buddy 90 | // buddy test hierarchies do not span multiple files, so they shouldn't be merged 91 | // putting file first makes sure filtering of buddy tests work for nested describe calls 92 | return switch (this) { 93 | case ClassName(className): 94 | className; 95 | case SuiteNameAndPos(name, fileName, lineNumber): 96 | '[$fileName:$lineNumber] $name'; 97 | case SuiteNameAndFile(name, fileName): 98 | '[$fileName] $name'; 99 | } 100 | #else 101 | return switch (this) { 102 | case ClassName(className): 103 | className; 104 | case SuiteNameAndPos(name, fileName, lineNumber): 105 | '$name [$fileName:$lineNumber]'; 106 | case SuiteNameAndFile(name, fileName): 107 | '$name [$fileName]'; 108 | } 109 | #end 110 | } 111 | } 112 | 113 | abstract LCOVFileName(String) from String { 114 | @:to 115 | public function toString():String { 116 | var regEx = ~/[^a-zA-Z0-9_.-]/g; 117 | return regEx.replace('${this}', "_"); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/data/TestFilter.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.data; 2 | 3 | import haxe.io.Path; 4 | 5 | using StringTools; 6 | 7 | #if (sys || nodejs) 8 | import haxe.Json; 9 | import sys.FileSystem; 10 | import sys.io.File; 11 | #end 12 | 13 | typedef TestFilterList = { 14 | include:Array, 15 | exclude:Array 16 | }; 17 | 18 | class TestFilter { 19 | var testFilters:TestFilterList; 20 | var baseFolder:String; 21 | var loaded:Bool; 22 | 23 | public function new(baseFolder:String) { 24 | this.baseFolder = baseFolder; 25 | testFilters = { 26 | include: [], 27 | exclude: [] 28 | }; 29 | loaded = false; 30 | } 31 | 32 | public function set(include:Array, exclude:Array) { 33 | testFilters.include = []; 34 | testFilters.exclude = []; 35 | for (f in include) { 36 | if (f.startsWith("root:")) { 37 | testFilters.include = []; 38 | break; 39 | } 40 | testFilters.include.push(f); 41 | } 42 | for (f in exclude) { 43 | testFilters.exclude.push(f); 44 | } 45 | save(baseFolder); 46 | } 47 | 48 | public function get():TestFilterList { 49 | if (!loaded) { 50 | load(baseFolder); 51 | } 52 | return testFilters; 53 | } 54 | 55 | public function clear() { 56 | testFilters.include = []; 57 | testFilters.exclude = []; 58 | save(baseFolder); 59 | } 60 | 61 | function save(?baseFolder:String) { 62 | #if (sys || nodejs) 63 | var fileName:String = getFileName(baseFolder); 64 | if (hasFilters(testFilters)) { 65 | Data.save(fileName, testFilters); 66 | } else { 67 | Data.clear(fileName); 68 | } 69 | #end 70 | } 71 | 72 | function load(?baseFolder:String) { 73 | testFilters.include = []; 74 | testFilters.exclude = []; 75 | #if (sys || nodejs) 76 | var fileName:String = getFileName(baseFolder); 77 | if (!FileSystem.exists(fileName)) { 78 | return; 79 | } 80 | var content:String = File.getContent(fileName); 81 | var filters:TestFilterList = Json.parse(content); 82 | for (filter in filters.include) { 83 | var reg:EReg = ~/ <[0-9]+>/; 84 | filter = reg.replace(filter, ""); 85 | testFilters.include.push(filter); 86 | } 87 | for (filter in filters.exclude) { 88 | var reg:EReg = ~/ <[0-9]+>/; 89 | filter = reg.replace(filter, ""); 90 | testFilters.exclude.push(filter); 91 | } 92 | #end 93 | loaded = true; 94 | } 95 | 96 | function getFileName(?baseFolder:String):String { 97 | return Path.join([baseFolder, Data.FOLDER, "filter.json"]); 98 | } 99 | 100 | public static function hasFilters(testFilters:TestFilterList):Bool { 101 | return (testFilters != null) && ((testFilters.include.length + testFilters.exclude.length) > 0); 102 | } 103 | 104 | public static function shouldRunTest(testFilters:TestFilterList, className:String, testName:String):Bool { 105 | if (!hasFilters(testFilters)) { 106 | return true; 107 | } 108 | var location:String = '$className.$testName'; 109 | for (filter in testFilters.exclude) { 110 | if (location == filter) { 111 | return false; 112 | } 113 | if (location.startsWith(filter + ".")) { 114 | return false; 115 | } 116 | } 117 | for (filter in testFilters.include) { 118 | if (location == filter) { 119 | return true; 120 | } 121 | if (location.startsWith(filter + ".")) { 122 | return true; 123 | } 124 | } 125 | return false; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/data/TestPositions.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.data; 2 | 3 | import haxe.io.Path; 4 | #if (sys || nodejs) 5 | import sys.FileSystem; 6 | import sys.io.File; 7 | #end 8 | #if !macro 9 | import json2object.JsonParser; 10 | #end 11 | import _testadapter.data.Data; 12 | 13 | typedef ClassPosition = { 14 | methods:Map}>, 15 | pos:Pos 16 | }; 17 | 18 | typedef Positions = Map; 19 | 20 | class TestPositions { 21 | var baseFolder:String; 22 | var positions:Positions; 23 | 24 | public function new(baseFolder:String, positions:Positions) { 25 | this.baseFolder = baseFolder; 26 | this.positions = positions; 27 | } 28 | 29 | public function add(className:String, ?testName:String, pos:Pos) { 30 | if (testName == null) { 31 | positions[className] = {methods: new Map(), pos: pos}; 32 | } else { 33 | if (positions[className] == null) { 34 | positions[className] = {methods: new Map(), pos: pos}; 35 | } 36 | positions[className].methods[testName] = {line: pos.line}; 37 | } 38 | } 39 | 40 | public function get(className:String, testName:String):Pos { 41 | var clazz = positions[className]; 42 | if ((clazz == null) || (clazz.pos == null) || (clazz.methods == null)) { 43 | return null; 44 | } 45 | if (testName == null) { 46 | return clazz.pos; 47 | } 48 | if (clazz.methods[testName] == null) { 49 | return clazz.pos; 50 | } 51 | return { 52 | file: clazz.pos.file, 53 | line: clazz.methods[testName].line 54 | }; 55 | } 56 | 57 | public function resolveClassName(fileName:String, lineNumber:Int):Null { 58 | for (clazz in positions.keys()) { 59 | var classPositions = positions.get(clazz); 60 | if (classPositions.pos.file != fileName) { 61 | continue; 62 | } 63 | if (classPositions.pos.line == lineNumber) { 64 | return clazz; 65 | } 66 | for (method in classPositions.methods.keys()) { 67 | var methodPos = classPositions.methods.get(method); 68 | if (methodPos.line == lineNumber) { 69 | return clazz; 70 | } 71 | } 72 | } 73 | return null; 74 | } 75 | 76 | public function save() { 77 | #if (sys || nodejs) 78 | Data.save(getFileName(baseFolder), positions); 79 | #end 80 | } 81 | 82 | public static function load(baseFolder:String):Null { 83 | #if (!macro && (sys || nodejs)) 84 | var fileName:String = getFileName(baseFolder); 85 | if (!FileSystem.exists(fileName)) { 86 | return null; 87 | } 88 | var content:String = File.getContent(fileName); 89 | 90 | var parser = new JsonParser(); 91 | var positions = parser.fromJson(content, fileName); 92 | return new TestPositions(baseFolder, positions); 93 | #else 94 | return new TestPositions(baseFolder, new Positions()); 95 | #end 96 | } 97 | 98 | static function getFileName(baseFolder:String):String { 99 | return Path.join([baseFolder, Data.FOLDER, "positions.json"]); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/data/TestResults.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.data; 2 | 3 | import haxe.Timer; 4 | import haxe.io.Path; 5 | import _testadapter.data.Data; 6 | #if (sys || nodejs) 7 | import sys.FileSystem; 8 | import sys.io.File; 9 | import json2object.JsonParser; 10 | #end 11 | 12 | class TestResults { 13 | var baseFolder:String; 14 | var suiteResults:TestSuiteResults; 15 | 16 | public var positions:TestPositions; 17 | 18 | public function new(baseFolder:String) { 19 | this.baseFolder = baseFolder; 20 | positions = TestPositions.load(baseFolder); 21 | suiteResults = load(baseFolder); 22 | } 23 | 24 | public function add(suiteId:SuiteId, testId:TestIdentifier, ?executionTime:Float, state:TestState, ?message:String, ?errorPos:Pos) { 25 | var line:Null = null; 26 | var className:String; 27 | var suitePos:Pos; 28 | switch (suiteId) { 29 | case ClassName(name): 30 | className = name; 31 | suitePos = positions.get(className, null); 32 | case SuiteNameAndPos(name, fileName, lineNumber): 33 | className = name; 34 | suitePos = {file: fileName, line: lineNumber}; 35 | case SuiteNameAndFile(name, fileName): 36 | className = name; 37 | suitePos = {file: fileName, line: 0}; 38 | } 39 | var testName:String; 40 | switch (testId) { 41 | case TestName(name): 42 | testName = name; 43 | var pos = positions.get(suiteId, name); 44 | if (pos != null) { 45 | line = pos.line; 46 | } 47 | case TestNameAndPos(name, _, lineNumber): 48 | testName = name; 49 | line = lineNumber; 50 | } 51 | function makeTest():TestMethodResults { 52 | return { 53 | name: testName, 54 | executionTime: executionTime, 55 | state: state, 56 | message: message, 57 | timestamp: Timer.stamp(), 58 | line: line, 59 | errorPos: errorPos 60 | } 61 | } 62 | for (data in suiteResults.classes) { 63 | if (data.id == suiteId) { 64 | data.methods = data.methods.filter(function(results) return results.name != testName); 65 | data.methods.push(makeTest()); 66 | return; 67 | } 68 | } 69 | suiteResults.classes.push({ 70 | id: suiteId, 71 | name: className, 72 | methods: [makeTest()], 73 | pos: suitePos 74 | }); 75 | } 76 | 77 | public function save() { 78 | #if (sys || nodejs) 79 | suiteResults.classes.sort(sortClasses); 80 | Data.save(getFileName(baseFolder), suiteResults); 81 | #end 82 | } 83 | 84 | function sortClasses(a:TestClassResults, b:TestClassResults):Int { 85 | if (a.id < b.id) { 86 | return -1; 87 | } 88 | if (a.id > b.id) { 89 | return 1; 90 | } 91 | return 0; 92 | } 93 | 94 | public static function clear(baseFolder:String) { 95 | #if (sys || nodejs) 96 | Data.clear(getFileName(baseFolder)); 97 | #end 98 | } 99 | 100 | public static function load(?baseFolder:String):TestSuiteResults { 101 | function emptySuite() { 102 | return {name: "root", classes: []}; 103 | } 104 | 105 | #if (sys || nodejs) 106 | var dataFile:String = getFileName(baseFolder); 107 | if (!FileSystem.exists(dataFile)) { 108 | return emptySuite(); 109 | } 110 | var content:String = File.getContent(dataFile); 111 | 112 | var parser = new JsonParser(); 113 | return parser.fromJson(content, dataFile); 114 | #else 115 | return emptySuite(); 116 | #end 117 | } 118 | 119 | static function getFileName(?baseFolder:String):String { 120 | return Path.join([baseFolder, getRelativeFileName()]); 121 | } 122 | 123 | public static function getRelativeFileName():String { 124 | return Path.join([Data.FOLDER, "results.json"]); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/haxeunit/Injector.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.haxeunit; 2 | 3 | #if macro 4 | import haxe.macro.Context; 5 | import haxe.macro.Expr; 6 | import _testadapter.data.TestFilter; 7 | 8 | using StringTools; 9 | using _testadapter.PatchTools; 10 | using _testadapter.data.Data; 11 | 12 | class Injector { 13 | public static function buildRunner():Array { 14 | var fields = Context.getBuildFields(); 15 | 16 | for (field in fields) { 17 | switch (field.name) { 18 | case "new": 19 | field.addInit(macro testResults = new _testadapter.data.TestResults($v{Sys.getCwd()})); 20 | case "run": 21 | field.name = "__run"; 22 | } 23 | } 24 | 25 | var extraFields = (macro class { 26 | var testResults:_testadapter.data.TestResults; 27 | 28 | public function run():Bool { 29 | var success:Bool = __run(); 30 | publishAdapterResults(); 31 | return success; 32 | } 33 | 34 | @:access(haxe.unit.TestResult) 35 | function publishAdapterResults() { 36 | for (r in result.m_tests) { 37 | var state:_testadapter.data.Data.TestState = Failure; 38 | var errorPos:Null<_testadapter.data.Data.Pos> = null; 39 | if (r.success) { 40 | state = Success; 41 | } else if (r.error != null) { 42 | if (StringTools.startsWith(r.error, "exception thrown : ")) { 43 | state = Error; 44 | } 45 | if (r.posInfos != null) { 46 | errorPos = {line: r.posInfos.lineNumber - 1, file: r.posInfos.fileName}; 47 | } 48 | } 49 | testResults.add(ClassName(r.classname), TestName(r.method), null, state, r.error, errorPos); 50 | } 51 | testResults.save(); 52 | } 53 | }).fields; 54 | return fields.concat(extraFields); 55 | } 56 | 57 | public static function buildCase():Array { 58 | var fields = Context.getBuildFields(); 59 | for (field in fields) { 60 | switch (field.kind) { 61 | case FFun(_) if (field.name.startsWith("test")): 62 | var clazz = Context.getLocalClass().get(); 63 | var suiteId:SuiteId = ClassName(clazz.pack.concat([clazz.name]).join(".")); 64 | if (!TestFilter.shouldRunTest(Macro.filters, suiteId, field.name)) { 65 | field.name = "disabled_" + field.name; 66 | } 67 | case _: 68 | } 69 | } 70 | return fields; 71 | } 72 | } 73 | #end 74 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/hexunit/Injector.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.hexunit; 2 | 3 | #if macro 4 | import haxe.macro.Context; 5 | import haxe.macro.Expr; 6 | 7 | using _testadapter.PatchTools; 8 | 9 | class Injector { 10 | public static function buildCore():Array { 11 | var fields = Context.getBuildFields(); 12 | for (field in fields) { 13 | switch (field.name) { 14 | case "new": 15 | field.addInit(macro addListener(new _testadapter.hexunit.Notifier($v{Sys.getCwd()}))); 16 | case "run": 17 | field.patch(Start, macro { 18 | var filterInclude = $v{Macro.filters.include}; 19 | var filterExclude = $v{Macro.filters.exclude}; 20 | if (filterInclude.length + filterExclude.length > 0) { 21 | var filteredClassDescriptors:Array = []; 22 | 23 | for (desc in _classDescriptors) { 24 | if (filterExclude.indexOf(desc.className) >= 0) { 25 | continue; 26 | } 27 | if (filterInclude.indexOf(desc.className) >= 0) { 28 | filteredClassDescriptors.push(desc); 29 | continue; 30 | } 31 | var filteredMethodDescriptors:Array = []; 32 | for (method in desc.methodDescriptors) { 33 | var name = desc.className + "." + method.methodName; 34 | if (filterExclude.indexOf(name) >= 0) { 35 | continue; 36 | } 37 | if (filterInclude.indexOf(name) >= 0) { 38 | filteredMethodDescriptors.push(method); 39 | } 40 | } 41 | if (filteredMethodDescriptors.length > 0) { 42 | desc.methodDescriptors = filteredMethodDescriptors; 43 | filteredClassDescriptors.push(desc); 44 | } 45 | } 46 | _classDescriptors = filteredClassDescriptors; 47 | } 48 | }); 49 | case _: 50 | } 51 | } 52 | return fields; 53 | } 54 | } 55 | #end 56 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/hexunit/Notifier.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.hexunit; 2 | 3 | import hex.unittest.description.ClassDescriptor; 4 | import hex.unittest.error.AssertException; 5 | import hex.unittest.event.ITestClassResultListener; 6 | import _testadapter.data.Data.Pos; 7 | import _testadapter.data.TestResults; 8 | 9 | using hex.unittest.description.ClassDescriptorUtil; 10 | 11 | class Notifier implements ITestClassResultListener { 12 | var testResults:TestResults; 13 | 14 | public function new(baseFolder:String) { 15 | testResults = new TestResults(baseFolder); 16 | } 17 | 18 | public function onStartRun(descriptor:ClassDescriptor):Void {} 19 | 20 | public function onEndRun(descriptor:ClassDescriptor):Void { 21 | testResults.save(); 22 | } 23 | 24 | public function onSuiteClassStartRun(descriptor:ClassDescriptor):Void {} 25 | 26 | public function onSuiteClassEndRun(descriptor:ClassDescriptor):Void {} 27 | 28 | public function onTestClassStartRun(descriptor:ClassDescriptor):Void {} 29 | 30 | public function onTestClassEndRun(descriptor:ClassDescriptor):Void {} 31 | 32 | public function onSuccess(descriptor:ClassDescriptor, timeElapsed:Float):Void { 33 | var methodDescriptor = descriptor.currentMethodDescriptor(); 34 | testResults.add(ClassName(descriptor.className), TestName(methodDescriptor.methodName), timeElapsed, Success); 35 | } 36 | 37 | public function onFail(descriptor:ClassDescriptor, timeElapsed:Float, error:hex.error.Exception):Void { 38 | var methodDescriptor = descriptor.currentMethodDescriptor(); 39 | var message = error.toString(); 40 | testResults.add(ClassName(descriptor.className), TestName(methodDescriptor.methodName), timeElapsed, Failure, message, getLineNumber(error)); 41 | } 42 | 43 | public function onTimeout(descriptor:ClassDescriptor, timeElapsed:Float, error:hex.error.Exception):Void { 44 | var methodDescriptor = descriptor.currentMethodDescriptor(); 45 | var message = error.toString(); 46 | testResults.add(ClassName(descriptor.className), TestName(methodDescriptor.methodName), timeElapsed, Error, message, getLineNumber(error)); 47 | } 48 | 49 | public function onIgnore(descriptor:ClassDescriptor):Void { 50 | var methodDescriptor = descriptor.currentMethodDescriptor(); 51 | testResults.add(ClassName(descriptor.className), TestName(methodDescriptor.methodName), null, Ignore); 52 | } 53 | 54 | function getLineNumber(error:hex.error.Exception):Null { 55 | if (Std.is(error, AssertException)) { 56 | var e:AssertException = cast error; 57 | return {line: e.posInfos.lineNumber - 1, file: e.posInfos.fileName}; 58 | } 59 | return null; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/instrument/Injector.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.instrument; 2 | 3 | #if macro 4 | import haxe.macro.Context; 5 | import haxe.macro.Expr; 6 | 7 | using _testadapter.PatchTools; 8 | 9 | class Injector { 10 | public static function buildCoverage():Array { 11 | var fields = Context.getBuildFields(); 12 | for (field in fields) { 13 | if (field.name == "endCoverage") { 14 | field.patch(End, macro { 15 | var reporter = new instrument.coverage.reporter.LcovCoverageReporter(haxe.io.Path.join([_testadapter.data.Data.FOLDER, "lcov.info"])); 16 | endCustomCoverage([reporter]); 17 | }); 18 | } 19 | } 20 | return fields; 21 | } 22 | } 23 | #end 24 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/munit/Injector.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.munit; 2 | 3 | #if macro 4 | import haxe.macro.Context; 5 | import haxe.macro.Expr; 6 | 7 | using _testadapter.PatchTools; 8 | 9 | class Injector { 10 | public static function buildRunner():Array { 11 | var fields = Context.getBuildFields(); 12 | var coverageEnabled:Null = Context.definedValue("instrument-coverage"); 13 | var baseFolder = haxe.io.Path.join([_testadapter.data.Data.FOLDER]); 14 | #if disable_attributable_coverage 15 | coverageEnabled = null; 16 | #end 17 | for (field in fields) { 18 | switch (field.name) { 19 | case "new": 20 | field.addInit(macro addResultClient(new _testadapter.munit.ResultClient($v{Sys.getCwd()}))); 21 | case "executeTestCases": 22 | field.patch(Replace, macro { 23 | #if (haxe_ver > 4.10) 24 | var isOfType = Std.isOfType; 25 | #else 26 | var isOfType = Std.is; 27 | #end 28 | for (c in clients) { 29 | if (isOfType(c, IAdvancedTestResultClient) && activeHelper.hasNext()) { 30 | var cl:IAdvancedTestResultClient = cast c; 31 | cl.setCurrentTestClass(activeHelper.className); 32 | } 33 | } 34 | activeHelper.before = clearCoverageForBefore(activeHelper.before); 35 | var afterFunc = activeHelper.after; 36 | for (testCaseData in activeHelper) { 37 | if (testCaseData.result.ignore) { 38 | ignoreCount++; 39 | for (c in clients) 40 | c.addIgnore(cast testCaseData.result); 41 | } else { 42 | activeHelper.after = attributeCoverageInAfter(afterFunc, activeHelper.className, testCaseData.result.name); 43 | testCount++; // note we don't include ignored in final test count 44 | tryCallMethod(activeHelper.test, activeHelper.before, emptyParams); 45 | testStartTime = Timer.stamp(); 46 | executeTestCase(testCaseData, testCaseData.result.async); 47 | if (!asyncPending) 48 | tryCallMethod(activeHelper.test, activeHelper.after, emptyParams); 49 | else 50 | break; 51 | } 52 | } 53 | }); 54 | } 55 | } 56 | if (coverageEnabled != null) { 57 | var extraFields = (macro class { 58 | function clearCoverageForBefore(oldBefore:Null):haxe.Constraints.Function { 59 | if (oldBefore == null) { 60 | return function() { 61 | instrument.coverage.Coverage.resetAttributableCoverage(); 62 | } 63 | } 64 | return function() { 65 | instrument.coverage.Coverage.resetAttributableCoverage(); 66 | oldBefore(); 67 | } 68 | } 69 | 70 | function attributeCoverageInAfter(oldAfter:haxe.Constraints.Function, className:String, testName:String):haxe.Constraints.Function { 71 | var testCaseName = '$className.$testName.lcov'; 72 | if (oldAfter == null) { 73 | return function() { 74 | var path = haxe.io.Path.join([$v{baseFolder}, testCaseName]); 75 | var lcovReporter = new instrument.coverage.reporter.LcovCoverageReporter(path); 76 | instrument.coverage.Coverage.reportAttributableCoverage([lcovReporter]); 77 | } 78 | } 79 | return function() { 80 | var path = haxe.io.Path.join([$v{baseFolder}, testCaseName]); 81 | var lcovReporter = new instrument.coverage.reporter.LcovCoverageReporter(path); 82 | instrument.coverage.Coverage.reportAttributableCoverage([lcovReporter]); 83 | oldAfter(); 84 | } 85 | } 86 | }).fields; 87 | fields = fields.concat(extraFields); 88 | } else { 89 | var extraFields = (macro class { 90 | inline function clearCoverageForBefore(oldBefore:Null):Null { 91 | return oldBefore; 92 | } 93 | 94 | inline function attributeCoverageInAfter(oldAfter:Null, className:String, 95 | testName:String):Null { 96 | return oldAfter; 97 | } 98 | }).fields; 99 | fields = fields.concat(extraFields); 100 | } 101 | return fields; 102 | } 103 | 104 | public static function buildHelper():Array { 105 | var fields = Context.getBuildFields(); 106 | for (field in fields) { 107 | switch (field.name) { 108 | case "scanForTests": 109 | field.patch(End, macro if (tests.length <= 0) { 110 | beforeClass = nullFunc; 111 | afterClass = nullFunc; 112 | before = nullFunc; 113 | after = nullFunc; 114 | }); 115 | case "addTest": 116 | field.patch(Start, macro { 117 | var suiteId:_testadapter.data.Data.SuiteId = ClassName(className); 118 | if (!_testadapter.data.TestFilter.shouldRunTest($v{Macro.filters}, suiteId, field)) { 119 | return; 120 | } 121 | }); 122 | case "after" | "before": 123 | switch (field.kind) { 124 | case FVar(t, e): 125 | case FFun(f): 126 | case FProp(get, set, t, e): 127 | field.kind = FVar(t, e); 128 | } 129 | case _: 130 | } 131 | } 132 | 133 | return fields; 134 | } 135 | } 136 | #end 137 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/munit/ResultClient.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.munit; 2 | 3 | import massive.munit.ITestResultClient; 4 | import massive.munit.TestResult; 5 | import _testadapter.data.Data.Pos; 6 | import _testadapter.data.TestResults; 7 | 8 | class ResultClient implements IAdvancedTestResultClient implements ICoverageTestResultClient { 9 | var testResults:TestResults; 10 | 11 | @:isVar public var completionHandler(get, set):ITestResultClient->Void; 12 | public var id(default, null):String; 13 | 14 | public function new(baseFolder) { 15 | testResults = new TestResults(baseFolder); 16 | } 17 | 18 | function get_completionHandler():ITestResultClient->Void { 19 | return completionHandler; 20 | } 21 | 22 | function set_completionHandler(value:ITestResultClient->Void):ITestResultClient->Void { 23 | return completionHandler = value; 24 | } 25 | 26 | public function addPass(result:TestResult) { 27 | testResults.add(ClassName(result.className), TestName(result.name), result.executionTime * 1000, Success); 28 | } 29 | 30 | public function addFail(result:TestResult) { 31 | var message:String = null; 32 | var errorPos:Null = null; 33 | if (result.failure != null) { 34 | message = result.failure.message; 35 | errorPos = {line: result.failure.info.lineNumber - 1, file: result.failure.info.fileName}; 36 | } 37 | testResults.add(ClassName(result.className), TestName(result.name), result.executionTime * 1000, Failure, message, errorPos); 38 | } 39 | 40 | public function addError(result:TestResult) { 41 | testResults.add(ClassName(result.className), TestName(result.name), result.executionTime * 1000, Error, Std.string(result.error)); 42 | } 43 | 44 | public function addIgnore(result:TestResult) { 45 | testResults.add(ClassName(result.className), TestName(result.name), result.executionTime * 1000, Ignore, result.description); 46 | } 47 | 48 | public function reportFinalStatistics(testCount:Int, passCount:Int, failCount:Int, errorCount:Int, ignoreCount:Int, time:Float):Dynamic { 49 | if (completionHandler != null) { 50 | completionHandler(this); 51 | } 52 | testResults.save(); 53 | return null; 54 | } 55 | 56 | public function setCurrentTestClass(className:String) {} 57 | 58 | public function setCurrentTestClassCoverage(result:CoverageResult) {} 59 | 60 | public function reportFinalCoverage(?percent:Float = 0, missingCoverageResults:Array, summary:String, ?classBreakdown:String, 61 | ?packageBreakdown:String, ?executionFrequency:String) {} 62 | } 63 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/tink_unittest/AttributableReporter.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.tink_unittest; 2 | 3 | import haxe.macro.Context; 4 | import _testadapter.data.Data; 5 | import _testadapter.data.TestResults; 6 | 7 | using tink.CoreApi; 8 | 9 | class AttributableReporter implements tink.testrunner.Reporter { 10 | var reporter:tink.testrunner.Reporter; 11 | var currentSuiteId:SuiteId; 12 | var currentCaseId:TestIdentifier; 13 | var baseFolder:String; 14 | 15 | public var testResults:TestResults; 16 | 17 | public function new(baseFolder:String, reporter:tink.testrunner.Reporter) { 18 | testResults = new TestResults(baseFolder); 19 | if (reporter == null) { 20 | reporter = new tink.testrunner.Reporter.BasicReporter(); 21 | } 22 | this.reporter = reporter; 23 | this.baseFolder = _testadapter.data.Data.FOLDER; 24 | } 25 | 26 | public function report(type:tink.testrunner.Reporter.ReportType):Future { 27 | switch (type) { 28 | case BatchStart: 29 | case BatchFinish(_): 30 | testResults.save(); 31 | case SuiteStart(info, _): 32 | currentSuiteId = SuiteNameAndPos(info.name, info.pos.fileName, info.pos.lineNumber - 1); 33 | case CaseStart(info, _): 34 | currentCaseId = TestNameAndPos(info.name, info.pos.fileName, info.pos.lineNumber - 1); 35 | instrument.coverage.Coverage.resetAttributableCoverage(); 36 | case Assertion(assertion): 37 | switch (assertion.holds) { 38 | case Success(_): 39 | testResults.add(currentSuiteId, currentCaseId, null, TestState.Success); 40 | case Failure(msg): 41 | if (msg == null) { 42 | msg = assertion.description; 43 | } 44 | testResults.add(currentSuiteId, currentCaseId, null, TestState.Failure, msg, 45 | {line: assertion.pos.lineNumber - 1, file: assertion.pos.fileName}); 46 | } 47 | case CaseFinish(result): 48 | var name = switch (currentCaseId) { 49 | case TestName(name): name; 50 | case TestNameAndPos(name, fileName, lineNumber): name; 51 | } 52 | 53 | var testCaseName:LCOVFileName = '${currentSuiteId}.$name.lcov'; 54 | var path = haxe.io.Path.join([baseFolder, testCaseName]); 55 | var lcovReporter = new instrument.coverage.reporter.LcovCoverageReporter(path); 56 | instrument.coverage.Coverage.reportAttributableCoverage([lcovReporter]); 57 | 58 | switch (result.result) { 59 | case Failed(msg): 60 | testResults.add(currentSuiteId, currentCaseId, null, TestState.Error, msg.toString(), 61 | {line: msg.pos.lineNumber - 1, file: msg.pos.fileName}); 62 | case Succeeded(asserts): 63 | if ((asserts == null) || (asserts.length <= 0)) { 64 | testResults.add(currentSuiteId, currentCaseId, null, TestState.Success); 65 | } 66 | case Excluded: 67 | testResults.add(currentSuiteId, currentCaseId, null, TestState.Ignore); 68 | } 69 | case SuiteFinish(_): 70 | } 71 | return reporter.report(type); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/tink_unittest/Injector.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.tink_unittest; 2 | 3 | #if macro 4 | import haxe.macro.Context; 5 | import haxe.macro.Expr; 6 | 7 | using _testadapter.PatchTools; 8 | 9 | class Injector { 10 | public static function buildRunner():Array { 11 | var fields = Context.getBuildFields(); 12 | var coverageEnabled:Null = Context.definedValue("instrument-coverage"); 13 | #if disable_attributable_coverage 14 | coverageEnabled = null; 15 | #end 16 | for (field in fields) { 17 | switch (field.name) { 18 | case "run": 19 | if (coverageEnabled != null) { 20 | field.addInit(Start, macro reporter = new _testadapter.tink_unittest.AttributableReporter($v{Sys.getCwd()}, reporter)); 21 | } else { 22 | field.addInit(Start, macro reporter = new _testadapter.tink_unittest.Reporter($v{Sys.getCwd()}, reporter)); 23 | } 24 | case "runCase": 25 | field.patch(Start, macro { 26 | var suiteId:_testadapter.data.Data.SuiteId = SuiteNameAndPos(suite.info.name, suite.info.pos.fileName, suite.info.pos.lineNumber - 1); 27 | if (!_testadapter.data.TestFilter.shouldRunTest($v{Macro.filters}, suiteId, caze.info.name)) { 28 | return Future.async(function(cb) { 29 | cb({ 30 | info: caze.info, 31 | result: tink.testrunner.Result.CaseResultType.Succeeded([]) 32 | }); 33 | }); 34 | } 35 | }); 36 | case _: 37 | } 38 | } 39 | return fields; 40 | } 41 | } 42 | #end 43 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/tink_unittest/Reporter.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.tink_unittest; 2 | 3 | import haxe.macro.Context; 4 | import _testadapter.data.Data; 5 | import _testadapter.data.TestResults; 6 | 7 | using tink.CoreApi; 8 | 9 | class Reporter implements tink.testrunner.Reporter { 10 | var reporter:tink.testrunner.Reporter; 11 | var currentSuiteId:SuiteId; 12 | var currentCaseId:TestIdentifier; 13 | 14 | public var testResults:TestResults; 15 | 16 | public function new(baseFolder:String, reporter:tink.testrunner.Reporter) { 17 | testResults = new TestResults(baseFolder); 18 | if (reporter == null) { 19 | reporter = new tink.testrunner.Reporter.BasicReporter(); 20 | } 21 | this.reporter = reporter; 22 | } 23 | 24 | public function report(type:tink.testrunner.Reporter.ReportType):Future { 25 | switch (type) { 26 | case BatchStart: 27 | case BatchFinish(_): 28 | testResults.save(); 29 | case SuiteStart(info, _): 30 | currentSuiteId = SuiteNameAndPos(info.name, info.pos.fileName, info.pos.lineNumber - 1); 31 | case CaseStart(info, _): 32 | currentCaseId = TestNameAndPos(info.name, info.pos.fileName, info.pos.lineNumber - 1); 33 | case Assertion(assertion): 34 | switch (assertion.holds) { 35 | case Success(_): 36 | testResults.add(currentSuiteId, currentCaseId, null, TestState.Success); 37 | case Failure(msg): 38 | if (msg == null) { 39 | msg = assertion.description; 40 | } 41 | testResults.add(currentSuiteId, currentCaseId, null, TestState.Failure, msg, 42 | {line: assertion.pos.lineNumber - 1, file: assertion.pos.fileName}); 43 | } 44 | case CaseFinish(result): 45 | switch (result.result) { 46 | case Failed(msg): 47 | testResults.add(currentSuiteId, currentCaseId, null, TestState.Error, msg.toString(), 48 | {line: msg.pos.lineNumber - 1, file: msg.pos.fileName}); 49 | case Succeeded(asserts): 50 | if ((asserts == null) || (asserts.length <= 0)) { 51 | testResults.add(currentSuiteId, currentCaseId, null, TestState.Success); 52 | } 53 | case Excluded: 54 | testResults.add(currentSuiteId, currentCaseId, null, TestState.Ignore); 55 | } 56 | case SuiteFinish(_): 57 | } 58 | return reporter.report(type); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/utest/Injector.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.utest; 2 | 3 | import haxe.macro.Compiler; 4 | #if macro 5 | import haxe.macro.Context; 6 | import haxe.macro.Expr; 7 | 8 | using _testadapter.PatchTools; 9 | 10 | class Injector { 11 | public static function build():Array { 12 | var fields = Context.getBuildFields(); 13 | var coverageEnabled:Null = Context.definedValue("instrument-coverage"); 14 | #if buddy 15 | // skip coverage modifications when buddy is enabled 16 | coverageEnabled = null; 17 | #end 18 | #if disable_attributable_coverage 19 | coverageEnabled = null; 20 | #end 21 | var baseFolder = haxe.io.Path.join([_testadapter.data.Data.FOLDER]); 22 | for (field in fields) { 23 | switch (field.name) { 24 | case "new": 25 | field.addInit(macro new _testadapter.utest.Reporter(this, $v{Sys.getCwd()})); 26 | case "addCase": // utest 2.x support 27 | #if haxe4 28 | #if (utest >= version("2.0.0-alpha")) 29 | field.patch(Replace, macro { 30 | var className = Type.getClassName(Type.getClass(testCase)); 31 | if (fixtures.exists(className)) { 32 | throw new UTestException('Cannot add the same test twice.'); 33 | } 34 | var newFixtures = []; 35 | var init:utest.TestData.InitializeUtest = (cast testCase : utest.TestData.Initializer).__initializeUtest__(); 36 | init.accessories.setup = clearCoverageForSetup(init.accessories.setup); 37 | var teardown = init.accessories.teardown; 38 | var cls:_testadapter.data.Data.SuiteId = ClassName(className); 39 | for (test in init.tests) { 40 | if (!isTestFixtureName(className, test.name, ['test', 'spec'], pattern, globalPattern)) { 41 | continue; 42 | } 43 | if (!_testadapter.data.TestFilter.shouldRunTest($v{Macro.filters}, cls, test.name)) { 44 | continue; 45 | } 46 | init.accessories.teardown = attributeCoverageInTeardown(teardown, cls, test.name); 47 | newFixtures.push(new utest.TestFixture(testCase, test, init.accessories)); 48 | } 49 | if (newFixtures.length > 0) { 50 | fixtures.set(className, { 51 | caseInstance: testCase, 52 | setupClass: init.accessories.getSetupClass(), 53 | dependencies: #if UTEST_IGNORE_DEPENDS [] #else init.dependencies #end, 54 | fixtures: newFixtures, 55 | teardownClass: init.accessories.getTeardownClass() 56 | }); 57 | length += newFixtures.length; 58 | } 59 | }); 60 | #end 61 | #end 62 | case "addITest": // utest 1.x support 63 | field.patch(Replace, macro { 64 | var className = Type.getClassName(Type.getClass(testCase)); 65 | if (iTestFixtures.exists(className)) { 66 | throw "Cannot add the same test twice."; 67 | } 68 | var fixtures = []; 69 | var init:utest.TestData.InitializeUtest = (cast testCase : utest.TestData.Initializer).__initializeUtest__(); 70 | init.accessories.setup = clearCoverageForSetup(init.accessories.setup); 71 | var teardown = init.accessories.teardown; 72 | var cls:_testadapter.data.Data.SuiteId = ClassName(className); 73 | for (test in init.tests) { 74 | if (!isTestFixtureName(cls, test.name, ["test", "spec"], pattern, globalPattern)) { 75 | continue; 76 | } 77 | if (!_testadapter.data.TestFilter.shouldRunTest($v{Macro.filters}, cls, test.name)) { 78 | continue; 79 | } 80 | init.accessories.teardown = attributeCoverageInTeardown(teardown, cls, test.name); 81 | var fixture = utest.TestFixture.ofData(testCase, test, init.accessories); 82 | addFixture(fixture); 83 | fixtures.push(fixture); 84 | } 85 | if (fixtures.length <= 0) { 86 | return; 87 | } 88 | iTestFixtures.set(className, { 89 | caseInstance: testCase, 90 | setupClass: init.accessories.getSetupClass(), 91 | dependencies: init.dependencies, 92 | fixtures: fixtures, 93 | teardownClass: init.accessories.getTeardownClass() 94 | }); 95 | }); 96 | } 97 | } 98 | if (coverageEnabled != null) { 99 | var extraFields = (macro class { 100 | function clearCoverageForSetup(oldSetup:Null<() -> utest.Async>):() -> utest.Async { 101 | if (oldSetup == null) { 102 | return function() { 103 | instrument.coverage.Coverage.resetAttributableCoverage(); 104 | return Async.getResolved(); 105 | } 106 | } 107 | return function() { 108 | instrument.coverage.Coverage.resetAttributableCoverage(); 109 | return oldSetup(); 110 | } 111 | } 112 | 113 | function attributeCoverageInTeardown(oldTeardown:Null<() -> utest.Async>, className:String, testName:String):() -> utest.Async { 114 | var testCaseName = '$className.$testName.lcov'; 115 | if (oldTeardown == null) { 116 | return function() { 117 | var path = haxe.io.Path.join([$v{baseFolder}, testCaseName]); 118 | var lcovReporter = new instrument.coverage.reporter.LcovCoverageReporter(path); 119 | instrument.coverage.Coverage.reportAttributableCoverage([lcovReporter]); 120 | return Async.getResolved(); 121 | } 122 | } 123 | return function() { 124 | var path = haxe.io.Path.join([$v{baseFolder}, testCaseName]); 125 | var lcovReporter = new instrument.coverage.reporter.LcovCoverageReporter(path); 126 | instrument.coverage.Coverage.reportAttributableCoverage([lcovReporter]); 127 | return oldTeardown(); 128 | } 129 | } 130 | }).fields; 131 | fields = fields.concat(extraFields); 132 | } else { 133 | var extraFields = (macro class { 134 | inline function clearCoverageForSetup(oldSetup:Null<() -> utest.Async>):Null<() -> utest.Async> { 135 | return oldSetup; 136 | } 137 | 138 | inline function attributeCoverageInTeardown(oldTeardown:Null<() -> utest.Async>, className:String, testName:String):Null<() -> utest.Async> { 139 | return oldTeardown; 140 | } 141 | }).fields; 142 | fields = fields.concat(extraFields); 143 | } 144 | return fields; 145 | } 146 | } 147 | #end 148 | -------------------------------------------------------------------------------- /test-adapter/_testadapter/utest/Reporter.hx: -------------------------------------------------------------------------------- 1 | package _testadapter.utest; 2 | 3 | import haxe.CallStack; 4 | import utest.Assertation; 5 | import utest.Runner; 6 | import utest.ui.common.ClassResult; 7 | import utest.ui.common.FixtureResult; 8 | import utest.ui.common.HeaderDisplayMode; 9 | import utest.ui.common.IReport; 10 | import utest.ui.common.PackageResult; 11 | import utest.ui.common.ResultAggregator; 12 | import _testadapter.data.Data.Pos; 13 | import _testadapter.data.Data.TestState; 14 | import _testadapter.data.TestResults; 15 | 16 | class Reporter implements IReport { 17 | public var displaySuccessResults:SuccessResultsDisplayMode; 18 | public var displayHeader:HeaderDisplayMode; 19 | 20 | var testResults:TestResults; 21 | var aggregator:ResultAggregator; 22 | 23 | public function new(runner:Runner, baseFolder:String) { 24 | testResults = new TestResults(baseFolder); 25 | displaySuccessResults = NeverShowSuccessResults; 26 | displayHeader = NeverShowHeader; 27 | aggregator = new ResultAggregator(runner, true); 28 | aggregator.onComplete.add(complete); 29 | } 30 | 31 | function complete(result:PackageResult) { 32 | for (packageName in result.packageNames()) { 33 | var pack:PackageResult = result.getPackage(packageName); 34 | for (className in pack.classNames()) { 35 | var cls:ClassResult = pack.getClass(className); 36 | for (testName in cls.methodNames()) { 37 | var fix:FixtureResult = cls.get(testName); 38 | var message = null; 39 | var state:TestState = Failure; 40 | var errorPos:Null = null; 41 | for (assertation in fix.iterator()) { 42 | switch (assertation) { 43 | case Assertation.Success(_): 44 | state = Success; 45 | case Assertation.Failure(msg, pos): 46 | state = Failure; 47 | message = msg; 48 | errorPos = {line: pos.lineNumber - 1, file: pos.fileName}; 49 | break; 50 | case Assertation.Error(e, s), Assertation.SetupError(e, s), Assertation.TeardownError(e, s), Assertation.AsyncError(e, s): 51 | state = Error; 52 | message = Std.string(e) + dumpStack(s); 53 | break; 54 | case Assertation.TimeoutError(missedAsyncs, s): 55 | state = Error; 56 | message = "missed async calls: " + missedAsyncs + dumpStack(s); 57 | break; 58 | case Assertation.Warning(msg): 59 | state = Failure; // ? 60 | message = msg; 61 | break; 62 | case Assertation.Ignore(reason): 63 | state = Ignore; 64 | message = reason; 65 | } 66 | } 67 | var dotPath = if (packageName == "") className else '$packageName.$className'; 68 | var executionTime:Null = null; 69 | if (Reflect.hasField(fix, "executionTime")) { 70 | executionTime = Reflect.field(fix, "executionTime"); 71 | } 72 | testResults.add(ClassName(dotPath), TestName(testName), executionTime, state, message, errorPos); 73 | } 74 | } 75 | } 76 | testResults.save(); 77 | } 78 | 79 | function dumpStack(stack:Stack):String { 80 | if (stack.length == 0) { 81 | return ""; 82 | } 83 | var parts = CallStack.toString(stack).split("\n"); 84 | var r = []; 85 | for (part in parts) { 86 | if (part.indexOf(" utest.") >= 0) { 87 | continue; 88 | } 89 | r.push(part); 90 | } 91 | return r.join("\n"); 92 | } 93 | 94 | public function setHandler(handler:Reporter->Void) {} 95 | } 96 | 97 | #if haxe4 98 | #if (utest >= version("2.0.0-alpha")) 99 | typedef Stack = CallStack; 100 | #else 101 | typedef Stack = Array; 102 | #end 103 | #else 104 | typedef Stack = Array; 105 | #end 106 | -------------------------------------------------------------------------------- /test-adapter/extraParams.hxml: -------------------------------------------------------------------------------- 1 | --macro _testadapter.Macro.init() -------------------------------------------------------------------------------- /test-adapter/haxelib.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test-adapter", 3 | "url": "https://github.com/vshaxe/haxe-test-adapter", 4 | "license": "MIT", 5 | "tags": [ 6 | "test", 7 | "testing", 8 | "vscode" 9 | ], 10 | "description": "A Test Adapter for Visual Studio Code", 11 | "version": "3.0.1", 12 | "releasenote": "added coverage support", 13 | "contributors": [ 14 | "AlexHaxe", 15 | "Gama11", 16 | "vshaxe" 17 | ], 18 | "dependencies": { 19 | "json2object": "" 20 | } 21 | } --------------------------------------------------------------------------------