1
0
Fork 0

til predictable seed data

This commit is contained in:
Ava Gaiety W 2023-10-25 11:45:40 -05:00
parent db45e19394
commit d38787806a
7 changed files with 30950 additions and 15 deletions

3
.obsidian/community-plugins.json vendored Normal file
View file

@ -0,0 +1,3 @@
[
"cm-editor-syntax-highlight-obsidian"
]

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,10 @@
{
"id": "cm-editor-syntax-highlight-obsidian",
"name": "Editor Syntax Highlight",
"author": "death_au",
"authorUrl": "https://github.com/deathau",
"description": "Show syntax highlighing in code blocks the editor",
"isDesktopOnly": false,
"version": "0.1.3",
"minAppVersion": "0.10.0"
}

View file

@ -0,0 +1,177 @@
@charset "UTF-8";
.cm-s-obsidian pre.HyperMD-codeblock span.cm-formatting-code-block {
color: var(--text-muted);
}
.cm-s-obsidian pre.HyperMD-codeblock .cm-keyword {
font-weight: normal;
}
.theme-dark .cm-s-obsidian {
/*
Name: yoncé
Author: Thomas MacLean (http://github.com/thomasmaclean)
Original yoncé color scheme by Mina Markham (https://github.com/minamarkham)
*/
/**/
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock {
color: #d4d4d4;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-keyword,
.theme-dark .cm-s-obsidian .cm-math.cm-keyword,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-keyword {
color: #00A7AA;
font-weight: normal;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-atom,
.theme-dark .cm-s-obsidian .cm-math.cm-atom,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-atom {
color: #F39B35;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-number,
.theme-dark .cm-s-obsidian .cm-math.cm-number,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-number {
color: #A06FCA;
}
.theme-dark .cm-s-obsidian span.cm-hmd-frontmatter.cm-type,
.theme-dark .cm-s-obsidian span.cm-math.cm-type,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock span.cm-type {
color: #A06FCA;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-def,
.theme-dark .cm-s-obsidian .cm-math.cm-def,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-def {
color: #98E342;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-property,
.theme-dark .cm-s-obsidian .cm-math.cm-property,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-property {
color: #D4D4D4;
}
.theme-dark .cm-s-obsidian span.cm-hmd-frontmatter.cm-variable,
.theme-dark .cm-s-obsidian span.cm-math.cm-variable,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock span.cm-variable {
color: #D4D4D4;
}
.theme-dark .cm-s-obsidian span.cm-hmd-frontmatter.cm-variable-2,
.theme-dark .cm-s-obsidian span.cm-math.cm-variable-2,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock span.cm-variable-2 {
color: #da7dae;
}
.theme-dark .cm-s-obsidian span.cm-hmd-frontmatter.cm-variable-3,
.theme-dark .cm-s-obsidian span.cm-math.cm-variable-3,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock span.cm-variable-3 {
color: #A06FCA;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-type.cm-def,
.theme-dark .cm-s-obsidian .cm-math.cm-type.cm-def,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-type.cm-def {
color: #FC4384;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-property.cm-def,
.theme-dark .cm-s-obsidian .cm-math.cm-property.cm-def,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-property.cm-def {
color: #FC4384;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-callee,
.theme-dark .cm-s-obsidian .cm-math.cm-callee,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-callee {
color: #FC4384;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-operator,
.theme-dark .cm-s-obsidian .cm-math.cm-operator,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-operator {
color: #FC4384;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-qualifier,
.theme-dark .cm-s-obsidian .cm-math.cm-qualifier,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-qualifier {
color: #FC4384;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-tag,
.theme-dark .cm-s-obsidian .cm-math.cm-tag,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-tag {
color: #FC4384;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-tag.cm-bracket,
.theme-dark .cm-s-obsidian .cm-math.cm-tag.cm-bracket,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-tag.cm-bracket {
color: #D4D4D4;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-attribute,
.theme-dark .cm-s-obsidian .cm-math.cm-attribute,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-attribute {
color: #A06FCA;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-comment,
.theme-dark .cm-s-obsidian .cm-math.cm-comment,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-comment {
color: #696d70;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-comment.cm-tag,
.theme-dark .cm-s-obsidian .cm-math.cm-comment.cm-tag,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-comment.cm-tag {
color: #FC4384;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-comment.cm-attribute,
.theme-dark .cm-s-obsidian .cm-math.cm-comment.cm-attribute,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-comment.cm-attribute {
color: #D4D4D4;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-string,
.theme-dark .cm-s-obsidian .cm-math.cm-string,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-string {
color: #E6DB74;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-string-2,
.theme-dark .cm-s-obsidian .cm-math.cm-string-2,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-string-2 {
color: #F39B35;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-meta,
.theme-dark .cm-s-obsidian .cm-math.cm-meta,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-meta {
color: #D4D4D4;
background: inherit;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-builtin,
.theme-dark .cm-s-obsidian .cm-math.cm-builtin,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-builtin {
color: #FC4384;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-header,
.theme-dark .cm-s-obsidian .cm-math.cm-header,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-header {
color: #da7dae;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-hr,
.theme-dark .cm-s-obsidian .cm-math.cm-hr,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-hr {
color: #98E342;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-link,
.theme-dark .cm-s-obsidian .cm-math.cm-link,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-link {
color: #696d70;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.cm-error,
.theme-dark .cm-s-obsidian .cm-math.cm-error,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .cm-error {
border-bottom: 1px solid #C42412;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.CodeMirror-activeline-background,
.theme-dark .cm-s-obsidian .cm-math.CodeMirror-activeline-background,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .CodeMirror-activeline-background {
background: #272727;
}
.theme-dark .cm-s-obsidian .cm-hmd-frontmatter.CodeMirror-matchingbracket,
.theme-dark .cm-s-obsidian .cm-math.CodeMirror-matchingbracket,
.theme-dark .cm-s-obsidian pre.HyperMD-codeblock .CodeMirror-matchingbracket {
outline: 1px solid grey;
color: #D4D4D4 !important;
}

View file

@ -4,16 +4,16 @@
"type": "split",
"children": [
{
"id": "7d6ba723d6838c71",
"id": "81700e831669a4f7",
"type": "tabs",
"children": [
{
"id": "43acf14268817221",
"id": "23b55eaa334e54e2",
"type": "leaf",
"state": {
"type": "markdown",
"state": {
"file": "content/tils/kagi_small_web.md",
"file": "content/tils/predictable_seed_data.md",
"mode": "source",
"source": false
}
@ -85,7 +85,7 @@
"state": {
"type": "backlink",
"state": {
"file": "content/tils/kagi_small_web.md",
"file": "content/tils/predictable_seed_data.md",
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
@ -112,7 +112,7 @@
"state": {
"type": "file-properties",
"state": {
"file": "content/tils/kagi_small_web.md"
"file": "content/tils/predictable_seed_data.md"
}
}
}
@ -121,7 +121,8 @@
}
],
"direction": "horizontal",
"width": 300
"width": 300,
"collapsed": true
},
"left-ribbon": {
"hiddenItems": {
@ -132,22 +133,26 @@
"markdown-importer:Open format converter": false
}
},
"active": "43acf14268817221",
"active": "23b55eaa334e54e2",
"lastOpenFiles": [
"images/Screenshot.md",
"content/tils/kagi_small_web.md",
"content/tils/pdf_obsidian_at_page.md",
"content/tils/asdf_direnv.md",
"content/tils/predictable_seed_data.md",
"content/til.md",
"content/images/Screenshot 2023-10-25 at 11.38.06 AM.png",
"content/tils/always_generated_ecto_boolean.md",
"images/Screenshot.md",
"images",
"_site/images/kagi-2.png",
"_site/images/kagi-1.png",
"_site/images/Screenshot 2023-10-02 at 12.51.03 PM.png",
"content/images/kagi-2.png",
"content/tils/pdf_obsidian_at_page.md",
"content/tils/struct_pattern_matching.md",
"_site/images/Screenshot 2023-10-02 at 12.48.45 PM.png",
"content/images/kagi-1.png",
"_site/tils/kagi_small_web/index.html",
"_site/tils/kagi_small_web",
"content/tils/always_generated_ecto_boolean.md",
"content/til.njk",
"_site/til/feed.xml",
"content/tils/til.njk",
@ -156,7 +161,6 @@
"_site/tils/pdf_obsidian_at_page/index.html",
"_site/tils/always_generated_ecto_boolean",
"_site/images/til-pdf-page.png",
"content/tils/asdf_direnv.md",
"node_modules/@11ty/eleventy-plugin-syntaxhighlight/README.md",
"node_modules/@11ty/eleventy-plugin-syntaxhighlight/test/issue-80/index.md",
"node_modules/@11ty/eleventy-plugin-syntaxhighlight/demo/test-markdown.md",
@ -175,10 +179,7 @@
"node_modules/minimist/README.md",
"node_modules/minimist/CHANGELOG.md",
"node_modules/@11ty/lodash-custom/README.md",
"node_modules/slugify/CHANGELOG.md",
"node_modules/markdown-it/node_modules/entities/readme.md",
"_site/images/ultimate-dungeon-terrain-3.jpg",
"_site/images/ultimate-dungeon-terrain-2.jpg",
"_site/images/ultimate-dungeon-terrain-1.jpg"
"_site/images/ultimate-dungeon-terrain-2.jpg"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

View file

@ -0,0 +1,84 @@
---
date: 2023-10-25
title: creating predictable seed data
---
A challenge appears when there's a requirement to create a _lot_ of unique seed data. Traditionally the developer community would reach for randomized libraries such as [Chance](https://chancejs.com/index.html) while generating data such as a new user with a random email, name, gender etc. This can lead to hard to automation test code as you cannot guarantee what a user's data will look like other than it's generic shape. One common solution is to write static [test fixtures](https://en.wikipedia.org/wiki/Test_fixture#Software) which come with their own problems such as difficulty scaling, updating, and interdependencies.
![Preview of a table of repeating yet unique and predictable content]("/images/Screenshot 2023-10-25 at 11.38.06 AM.png")
Instead, what if we tied randomness to a static value such as an index within a loop (this can also be done with [static seeds](https://chancejs.com/usage/seed.html)). In the following examples we'll utilize a simple loop to create various types of predictable data.
```elixir
@def create_transaction do
count_to_generate = 150
amount_multiplier = 100
Enum.map(1..count_to_generate, fn index ->
# Example creating a money transaction
App.Transactions.create_transaction(%{
amount: &1 * amount_multiplier,
} end)
)
end
# Creates transactions with amounts tied to the index modified by some amount
# Ex: [%{amount: 100}, %{amount: 200}... %{amount: 15,000}]
```
But sure, you're saying this may only work for numbers. Well we can get clever and leverage looping over lists as well with this helper function...
```elixir
@doc """
Allows for being given a list, then passing the current index
to loop over the results like A, B, C, A, B, C...
## Examples
iex> repeating_loop_through_list(["A", "B", "C"], 1)
"B"
iex> repeating_loop_through_list(["A", "B", "C"], 3)
"A"
"""
@spec repeating_loop_through_list(list(), integer()) :: any()
def repeating_loop_through_list(list, index),
do: Enum.at(list, Integer.mod(index, Enum.count(list)))
```
With the above function we now can tie indexes to a list of repeating options.
```elixir
currencies = ["USD", "RUB", "JPY"]
Enum.map(1..count_to_generate, fn index ->
App.Transactions.create_transaction(%{
currency: repeating_loop_through_list(currencies, index),
})
end)
# Ex: [%{currency: "USD"}, %{currency: "RUB"}... %{currency: "USD"}]
```
Another fun trick is to leverage string padding to create example ID's or "codes" that may be tied to each item you're generating. I find this particularly useful while testing sorting.
```elixir
code_length = 3
padding_character = "0"
Enum.map(1..count_to_generate, fn index ->
App.Transactions.create_transaction(%{
code: String.pad_leading(to_string(index), code_length, padding_character),
})
end)
# Ex: [%{code: "001"}, %{code: "002"}... %{code: "150"}]
```
This works for dates as well!
```elixir
date_year = 2023
date_month = 01
max_date_day = 30
Enum.map(1..count_to_generate, fn index ->
App.Transactions.create_transaction(%{
sent_date: Date.new!(date_year, date_month, min(index, max_date_day)),
})
end)
# Ex: [%{date: ~D[2023-01-01]}, %{date: ~D[2023-01-02]}]
```
At the end of the day, this is just example test data. Good is better than perfect and so long as you're shipping something that looks and feels like the final product you're doing yourself, other developers, and QA a service.