SalesForce開発のTips(備忘録)
SalesForce Apexのテストの備忘録
コードカバー率の調査
開発者コンソールの [Query Editor]タブで[Use Tooling API] をチェックして、下記A or Bを実行
- A.クラス単位で見たい場合
SELECT ApexClassOrTrigger.Name, NumLinesCovered, NumLinesUncovered FROM ApexCodeCoverageAggregate WHERE ApexClassOrTrigger.Name = 'ApexClassName'
- B.メソッド単位で見たい場合
SELECT ApexTestClass.Name,TestMethodName,NumLinesCovered,NumLinesUncovered FROM ApexCodeCoverage WHERE ApexClassOrTrigger.Name = 'ApexClassName'
SalesForce エラーハンドリングの備忘録
参考
Error Handling Best Practices for Lightning and Apex | Developer Force Blog
exception handling best practises - Salesforce Developer Community
【CircleCI】CircleCI 2.0でE2Eテスト(Kotlin・Junit・Selenium・Selenide)を実行してみた
CircleCiでSelenideを実行してみた
ソースはこちら
github.com
環境・言語
- OS
- macOS Mojave 10.14.5
- language
- kotlin 1.3.31
前提条件
- Homebrewがインストールされている(Homebrew 2.1.6)
- gradleがインストールされている(Gradle 5.5)
- javaがインストールされている(openjdk 11.0.2 2018-10-16)
- githubにログインできる(登録している)
- githubで空のリポジトリを作成している
プロジェクト作成(gradle)
mkdir hoge cd hoge gradle init --type kotlin-application
build.gradle(上記gradle init
にて生成されたファイルを修正)
plugins { id 'org.jetbrains.kotlin.jvm' version '1.3.31' id 'application' } apply plugin: 'kotlin' apply plugin: 'java' apply plugin: 'idea' repositories { mavenCentral() } dependencies { implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' implementation 'com.codeborne:selenide:5.2.4' testImplementation 'org.jetbrains.kotlin:kotlin-test' testImplementation 'org.jetbrains.kotlin:kotlin-test-junit' }
テストクラス(/src/test/kotlin/e2e/test/MainTest.kt
)
import kotlin.test.Test import kotlin.test.assertTrue class MainTest { @Test fun mainTest() { // ChromeDriver を headless モードで利用 Configuration.browser = WebDriverRunner.CHROME Configuration.headless = true Configuration.reportsFolder = "test-result/reports" Configuration.browserSize = "1024x768" // Googleトップページ // "selenide"を検索 open("https://www.google.co.jp/") `$`("input[type=text]").`val`("selenide").pressEnter() // 検索ページ // Selenideの公式ページをクリック `$`(byText("Selenide: concise UI tests in Java")).click() // Selenide公式ページ // 「What is Selenide?」という文言があることを確認 `$`("body").shouldHave(text("What is Selenide?")) } }
githubリポジトリにpush
git init git remote add origin {github-target-repository} git commit -m 'first commit' git push origin master
Circle Ci に登録
Circle Ci config.yml作成
上記のプロジェクト直下で
touch .circleci/config.yml
- .circleci/config.yml
version: 2 jobs: build: docker: - image: circleci/openjdk:11.0.2-jdk-browsers working_directory: ~/repo steps: - checkout - restore_cache: keys: # when lock file changes, use increasingly general patterns to restore cache - gradle-repo-v1-{{ .Branch }}-{{ checksum "build.gradle" }} - gradle-repo-v1-{{ .Branch }}- - gradle-repo-v1- - run: name: Library check command: | gradle dependencies - save_cache: paths: - ~/.gradle key: gradle-repo-v1-{{ .Branch }}-{{ checksum "build.gradle" }} - run: name: Run Tests command: gradle test - run: name: Save test results command: | mkdir -p ~/test-results/junit/ find . -type f -regex ".*/build/test-results/.*xml" -exec cp -p {} ~/test-results/junit/ \; mkdir -p ~/test-results/reports/ find . -type d -regex ".*/build/reports" -exec cp -rp {} ~/test-results/ \; when: always - store_test_results: path: ~/test-results - store_artifacts: path: ~/test-results/junit - store_artifacts: path: ~/test-results/reports workflows: version: 2 # push時のテスト実行用(workflowを使用すると、このworkflow(triggersの設定がなくjobを指定した)がないとpush時にjobが実行されない) normal_workflow: jobs: - build # スケジュールテスト実行用 schedule_workflow: triggers: - schedule: cron: "1 3 1 * *" # UTCで記述。-9hours filters: branches: only: - master jobs: - build
CircleCI CLIインストール
brew install circleci
下記を参照
circleci.com
.circleci/config.yml
のチェック
circleci config validate
Config file at .circleci/config.yml is valid.
が出力されればOK。それ以外はエラーメッセージに書かれた内容に沿って対応。
- ローカルで
.circleci/config.yml
のテスト
circleci local execute --job build
Circle Ci にプロジェクト追加
normal_workflow
の設定があることにより、上記でjobが実行される
結果の確認
まとめ
circleciのdocker imageが良いですね。
circleci/openjdk:11.0.2-jdk-browsers
無料枠で十分使えるので、楽だしこれから機会があればどんどん使いたいなぁ
250分/週かな?...
Usage Plan - CircleCI
ただし、下記のようなIPの制限があるので、それがネックになる場合は他が良さそうです。
IP アドレスのホワイトリスト登録 – CircleCI Japanese Support Center
参考
CircleCIのドキュメントへようこそ - CircleCI Gradle User Manual
intelliJでbuild Project時にwebpackのビルドも実行させてみた
intelliJのbuild / runアクションをgradleに委任
intelliJでgradleプロジェクトのビルド時にwebpackのビルドも実行したかったのでbuild.gradleにnpm install
とnpm run build
(webpack)を実行する処理をbuild.gradleに実装し、毎ビルド時にbuilde.gradleが読み込まれるように設定してみた。
環境・言語
- IDE
- intelliJ idea 2018.3.4
- backend-framework
- Spring boot 2
- backend-language
- kotlin
- frontend-framework
- vue.js
- frontend-language
- html
- css
- javascript
gradleプロジェクト追加したファイル
/package json
{ "name": "hogehoge", "version": "1.0.0", "description": "hoge", "repository": { "type": "git", "url": "hogehoge.git" }, "license": "ISC", "devDependencies": { "@babel/core": "^7.3.4", "babel-cli": "^6.26.0", "babel-loader": "^8.0.5", "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-env": "^1.7.0", "copy-webpack-plugin": "^5.0.0", "css-loader": "^2.1.1", "lite-server": "^2.4.0", "vue-html-loader": "^1.2.4", "vue-loader": "^15.7.0", "vue-style-loader": "^4.1.2", "webpack": "^4.29.6", "webpack-cli": "^3.2.3" }, "dependencies": { "vue": "^2.6.8", "vue-router": "^3.0.2" }, "scripts": { "build": "webpack", } }
/webpack.config.js
const path = require('path'); const { VueLoaderPlugin } = require('vue-loader'); module.exports = { mode: "development", entry: { console: path.join(__dirname, 'src', 'main', 'node', 'pages', 'console', 'main.js'), }, output: { path: path.join(__dirname, 'src', 'main', 'resources', 'static', 'js'), filename: '[name].bundle.js' }, module: { rules: [ { test: /\.css$/, use: [ 'style-loader', {loader: 'css-loader', options: {url: false}}, ] }, { test: /\.vue$/, use: [{loader: 'vue-loader'}] } ] }, resolve: { extensions: ['.js', '.vue'], modules: [ "node_modules" ], alias: { vue: 'vue/dist/vue.common.js' } }, devtool: 'source-map', plugins: [ new VueLoaderPlugin() ] };
/build.gradle
plugins { id 'org.springframework.boot' version '2.1.2.RELEASE' id 'org.jetbrains.kotlin.jvm' version '1.2.71' id 'org.jetbrains.kotlin.plugin.spring' version '1.2.71' } apply plugin: 'io.spring.dependency-management' bootJar{ archiveName "hogehoge.jar" launchScript() } group = 'test.hogehoge' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-data-redis' implementation 'org.springframework.session:spring-session-data-redis' implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'com.fasterxml.jackson.module:jackson-module-kotlin' implementation 'org.jetbrains.kotlin:kotlin-reflect' implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8' implementation 'org.mariadb.jdbc:mariadb-java-client:2.4.0' runtimeOnly 'org.springframework.boot:spring-boot-devtools' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' } compileKotlin { kotlinOptions { freeCompilerArgs = ['-Xjsr305=strict'] jvmTarget = '1.8' } } compileTestKotlin { kotlinOptions { freeCompilerArgs = ['-Xjsr305=strict'] jvmTarget = '1.8' } } task npmRunBuild { doLast { def npm = System.getProperty('os.name').contains('Windows') ? 'cmd /c npm' : 'npm' if (file('./node_modules').exists() == false) { "${npm} install".execute().waitForProcessOutput(System.out, System.err) } "${npm} run build".execute().waitForProcessOutput(System.out, System.err) } } processResources.dependsOn npmRunBuild
動作確認
この状態でintelliJのBuild Project、もしくはRun Applicationを実行!
実行前には存在しなかった/node_modules
やpackage-lock.json
が生成されました。
まとめ
vue.js側を更新した際にいちいち npm run build
を実行しなければならないところをrunのみで、 全てbuildされて動作確認できるようになりました。