[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-7451":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":22,"hasPages":24,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":26,"readmeContent":27,"aiSummary":28,"trendingCount":16,"starSnapshotCount":16,"syncStatus":29,"lastSyncTime":30,"discoverSource":31},7451,"paparazzi","cashapp\u002Fpaparazzi","cashapp","Render your Android screens without a physical device or emulator","https:\u002F\u002Fcashapp.github.io\u002Fpaparazzi\u002F",null,"Kotlin",2591,253,34,142,0,3,27,1,29.21,"Apache License 2.0",false,"master",true,[],"2026-06-12 02:01:39","Paparazzi\n========\n\nAn Android library to render your application screens without a physical device or emulator.\n\n```kotlin\nclass LaunchViewTest {\n  @get:Rule\n  val paparazzi = Paparazzi(\n    deviceConfig = PIXEL_5,\n    theme = \"android:Theme.Material.Light.NoActionBar\"\n    \u002F\u002F ...see docs for more options\n  )\n\n  @Test\n  fun launchView() {\n    val view = paparazzi.inflate\u003CLaunchView>(R.layout.launch)\n    \u002F\u002F or...\n    \u002F\u002F val view = LaunchView(paparazzi.context)\n\n    view.setModel(LaunchModel(title = \"paparazzi\"))\n    paparazzi.snapshot(view)\n  }\n\n  @Test\n  fun launchComposable() {\n    paparazzi.snapshot {\n      MyComposable()\n    }\n  }\n}\n```\n\nSee the [project website][paparazzi] for documentation and APIs.\n\nSupporting Multiple Test Frameworks\n-------\n\n### JUnit Jupiter\n\n```kotlin\nlateinit var paparazzi: Paparazzi\n\n@BeforeEach\nfun setup(testInfo: TestInfo) {\n  paparazzi = Paparazzi().apply {\n    setup(\n      testName = TestName(\n        packageName = testInfo.testClass.get().`package`?.name.orEmpty(),\n        className = testInfo.testClass.get().simpleName,\n        methodName = testInfo.testMethod.get().name\n      )\n    )\n  }\n}\n\n@AfterEach\nfun tearDown() {\n  paparazzi.teardown()\n}\n\n@Test\nfun snapshot_example() {\n  val view = paparazzi.inflate\u003CTextView>(android.R.layout.simple_list_item_1).apply {\n    text = \"Hello Paparazzi\"\n    textSize = 24f\n    gravity = Gravity.CENTER\n  }\n\n  paparazzi.snapshot(view)\n}\n```\n\n### Kotest\n\n```kotlin\nclass PaparazziKotestListener(\n  val api: Paparazzi\n) : TestListener {\n\n  override suspend fun beforeTest(testCase: TestCase) {\n    api.setup(testCase.toTestName())\n    super.beforeTest(testCase)\n  }\n\n  override suspend fun afterTest(testCase: TestCase, result: TestResult) {\n    super.afterTest(testCase, result)\n    api.teardown()\n  }\n\n  private fun TestCase.toTestName() =\n    TestName(\n      packageName = this.spec::class.java.`package`?.name.orEmpty(),\n      className = this::class.simpleName.orEmpty(),\n      methodName = this.name.testName\n    )\n}\n```\n\nWhere you can use the Kotest listener like so:\n\n```kotlin\nclass KotestPaparazziTest : FunSpec({\n\n  val listener = PaparazziKotestListener(Paparazzi())\n  listeners(listener)\n\n  test(\"verify paparazzi snapshot works with kotest listener\") {\n    val textView = listener.api.inflate\u003CTextView>(android.R.layout.simple_list_item_1)\n    textView.apply {\n      text = \"Kotest FunSpec Snapshot\"\n      textSize = 24f\n      gravity = Gravity.CENTER\n    }\n    listener.api.snapshot(textView)\n  }\n})\n```\n\n### TestNg\n\n```kotlin\nclass TestNgPaparazziTest {\n\n  lateinit var paparazzi: Paparazzi\n\n  @BeforeMethod\n  fun setup(result: ITestResult) {\n    val testMethod = result.method\n    val className = testMethod.realClass.simpleName\n    val methodName = testMethod.methodName\n    val packageName = testMethod?.realClass?.`package`?.name.orEmpty()\n\n    val testName = TestName(packageName, className, methodName)\n\n    paparazzi = Paparazzi()\n    paparazzi.setup(testName = testName)\n  }\n\n  @AfterMethod\n  fun tearDown() {\n    paparazzi.teardown()\n  }\n\n  @Test\n  fun `verify testng snapshot`() {\n    val textView = paparazzi.inflate\u003CTextView>(android.R.layout.simple_list_item_1).apply {\n      text = \"Paparazzi TestNg test\"\n      textSize = 24f\n      gravity = Gravity.CENTER\n    }\n\n    paparazzi.snapshot(textView)\n  }\n}\n```\n\nTasks\n-------\n\n```bash\n.\u002Fgradlew :sample:testDebug\n```\n\nRuns tests and generates an HTML report at `sample\u002Fbuild\u002Freports\u002Fpaparazzi\u002F` showing all\ntest runs and snapshots.\n\n```bash\n.\u002Fgradlew :sample:recordPaparazziDebug\n```\n\nSaves snapshots as golden values to a predefined source-controlled location\n(defaults to `src\u002Ftest\u002Fsnapshots`).\n\n```bash\n.\u002Fgradlew :sample:verifyPaparazziDebug\n```\n\nRuns tests and verifies against previously-recorded golden values. Failures generate diffs at `sample\u002Fbuild\u002Fpaparazzi\u002Ffailures`.\n\nFor more examples, check out the [sample][sample] project.\n\nGit LFS\n--------\nIt is recommended you use [Git LFS][lfs] to store your snapshots.  Here's a quick setup:\n\n```bash\nbrew install git-lfs\ngit config core.hooksPath  # optional, confirm where your git hooks will be installed\ngit lfs install --local\ngit lfs track \"**\u002Fsnapshots\u002F**\u002F*.png\"\ngit add .gitattributes\n# Optional to improve git checkout performance\ngit config lfs.setlockablereadonly false\n```\n\nOn CI, you might set up something like:\n\n`$HOOKS_DIR\u002Fpre-receive`\n```bash\n# compares files that match .gitattributes filter to those actually tracked by git-lfs\ndiff \u003C(git ls-files ':(attr:filter=lfs)' | sort) \u003C(git lfs ls-files -n | sort) >\u002Fdev\u002Fnull\n\nret=$?\nif [[ $ret -ne 0 ]]; then\n  echo >&2 \"This remote has detected files committed without using Git LFS. Run 'brew install git-lfs && git lfs install' to install it and re-commit your files.\";\n  exit 1;\nfi\n```\n\n`your_build_script.sh`\n```bash\nif [[ is running snapshot tests ]]; then\n  # fail fast if files not checked in using git lfs\n  \"$HOOKS_DIR\"\u002Fpre-receive\n  git lfs install --local\n  git lfs pull\nfi\n```\n\nJetifier\n--------\n\nIf using Jetifier to migrate off Support libraries, add the following to your `gradle.properties` to\nexclude bundled Android dependencies.\n\n```properties\nandroid.jetifier.ignorelist=android-base-common,common\n```\n\nLottie\n--------\n\nWhen taking screenshots of Lottie animations, you need to force Lottie to not run on a background thread, otherwise Paparazzi can throw exceptions [#494](https:\u002F\u002Fgithub.com\u002Fcashapp\u002Fpaparazzi\u002Fissues\u002F494), [#630](https:\u002F\u002Fgithub.com\u002Fcashapp\u002Fpaparazzi\u002Fissues\u002F630).\n\n```kotlin\n@Before\nfun setup() {\n    LottieTask.EXECUTOR = Executor(Runnable::run)\n}\n```\n\nLocalInspectionMode\n--------\nSome Composables -- such as `GoogleMap()` -- check for `LocalInspectionMode` to short-circuit to a `@Preview`-safe Composable.\n\nHowever, Paparazzi does not set `LocalInspectionMode` globally to ensure that the snapshot represents the true production output, similar to how it overrides `View.isInEditMode` for legacy views.\n\nAs a workaround, we recommend wrapping such a Composable in a custom Composable with a `CompositionLocalProvider` and setting `LocalInspectionMode` there.\n\n```kotlin\n @Test\n  fun inspectionModeView() {\n    paparazzi.snapshot(\n      CompositionLocalProvider(LocalInspectionMode provides true) {\n        YourComposable()\n      }\n    )\n  }\n```\n\nReleases\n--------\n\nOur [change log][changelog] has release history.\n\nUsing plugin application:\n```groovy\nbuildscript {\n  repositories {\n    mavenCentral()\n    google()\n  }\n  dependencies {\n    classpath 'app.cash.paparazzi:paparazzi-gradle-plugin:2.0.0-alpha04'\n  }\n}\n\napply plugin: 'app.cash.paparazzi'\n```\n\nUsing the plugins DSL:\n```groovy\nplugins {\n  id 'app.cash.paparazzi' version '2.0.0-alpha04'\n}\n```\n\nSnapshots of the development version are available in [the Central Portal Snapshots repository][snap].\n\n```groovy\nrepositories {\n  \u002F\u002F ...\n  maven {\n    url 'https:\u002F\u002Fcentral.sonatype.com\u002Frepository\u002Fmaven-snapshots\u002F'\n  }\n}\n```\n\nLicense\n-------\n\n```\nCopyright 2019 Square, Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http:\u002F\u002Fwww.apache.org\u002Flicenses\u002FLICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n\n [paparazzi]: https:\u002F\u002Fcashapp.github.io\u002Fpaparazzi\u002F\n [sample]: https:\u002F\u002Fgithub.com\u002Fcashapp\u002Fpaparazzi\u002Ftree\u002Fmaster\u002Fsample\n [lfs]: https:\u002F\u002Fgit-lfs.github.com\u002F\n [changelog]: https:\u002F\u002Fcashapp.github.io\u002Fpaparazzi\u002Fchangelog\u002F\n [snap]: https:\u002F\u002Fcentral.sonatype.com\u002Fservice\u002Frest\u002Frepository\u002Fbrowse\u002Fmaven-snapshots\u002Fapp\u002Fcash\u002Fpaparazzi\u002F\n","Paparazzi 是一个用于在没有物理设备或模拟器的情况下渲染Android应用界面的库。它支持使用Kotlin编写测试代码，能够通过简单的API调用创建屏幕截图，并且兼容多种测试框架如JUnit Jupiter、Kotest和TestNg，使得开发者可以在不同环境下轻松集成UI测试。该工具特别适合于需要频繁进行UI验证而不想依赖于真实设备或模拟器运行的应用开发场景，从而提高开发效率与测试覆盖率。",2,"2026-06-11 03:12:33","top_language"]