-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
144 lines (69 loc) · 52.6 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>[代码练习] 喝100杯奶茶</title>
<link href="/posts/dec0d091/"/>
<url>/posts/dec0d091/</url>
<content type="html"><![CDATA[<blockquote><p>QQ水群时看到这么一个段子,虽然段子很老套,但这么工整一段话段话看起来就让人手痒,就做一个代码练习吧。</p></blockquote><p><img src="/img/HaveACup/image1.png" alt="image1.png"></p><p>写一个能随机生成这段话的代码。但是如果只是一模一样的生成就有点太无聊了,最好是能根据输入的词能够按这样的模板输出。</p><p>也就是将 “喝xx杯奶茶”提取出来,然后根据提取词随机生成。</p><h1 id="提取数字与汉字"><a href="#提取数字与汉字" class="headerlink" title="提取数字与汉字"></a>提取数字与汉字</h1><p>把数字与汉字分别提取出来,存储在一个<code>[]string</code>切片中 也就是<code>[][]string</code></p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">preParam</span><span class="params">()</span></span> [][]<span class="type">string</span> {</span><br><span class="line"><span class="keyword">var</span> s = <span class="string">"喝100杯奶茶\n来99个拥抱\n看98场日落\n要97次接吻\n拍96张照片\n买95朵玫瑰\n去94家餐馆\n看93次大海\n走92条小巷\n打91次雨伞\n要90场牵手\n种89个草莓\n盖88次被子\n递87杯温水\n热86次剩饭\n看85次电影\n做84顿午饭\n切83个水果\n吃82次甜品\n喝81次暖茶\n要80次拥抱\n吃79遍烧烤\n烤78次肉串\n涮77次火锅\n来76次海鲜\n吃75种小吃\n参74场晚宴\n喝73杯喜酒\n吃72次西餐\n尝71颗糖果\n给你70枚吻\n荡69遍秋千\n看68次日出\n躺67次草地\n看66次星空\n闻65次头发\n抱64次肩膀\n吻63次脸颊\n亲62次锁骨\n咬61次耳朵\n有60次相拥\n看59场鬼片\n去58个城市\n吃57桶米花\n逛56个商厦\n打55次的士\n坐54次公交\n等53次地铁\n开52次自驾\n站51遍路灯\n睡50次怀里\n去49个鬼屋\n看48场表演\n逗47只动物\n坐46次飞车\n玩45次激流\n滑44次滑梯\n坐43次飞椅\n转42次陀螺\n吊41次吊索\n吃40次小吃\n捂39次肚子\n揉38次肩膀\n捶37次后背\n捏36次小腿\n暖35次脚丫\n摸34次脑袋\n撮33次肋骨\n挠32次手心\n逗31场大笑\n要30次拥吻\n放29个气球\n钓28只大鱼\n玩27次飞镖\n放26次风筝\n冲25次瀑布\n滑24艘小船\n蹦23场蹦极\n跳22次跳伞\n漂21次河流\n生20次闷气\n骑19次单车\n看18场大雪\n玩17遍飞艇\n去16次森林\n探15个峡谷\n踏14个小溪\n爬13座高山\n看12个沙漠\n坐11次轮船\n写10封情书\n唱9首情歌\n堆8个雪人\n摘7朵野花\n看6场流星\n许5个愿望\n醉4次夜酒\n种3棵玫瑰\n吵2次架\n爱1辈子"</span></span><br><span class="line">m := extractKeyValuePairs(s)</span><br><span class="line"><span class="keyword">return</span> m</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">extractKeyValuePairs</span><span class="params">(sentence <span class="type">string</span>)</span></span> [][]<span class="type">string</span> {</span><br><span class="line">resultMap := <span class="built_in">make</span>([][]<span class="type">string</span>, <span class="number">100</span>)</span><br><span class="line"><span class="comment">//将句子拆分为行</span></span><br><span class="line">lines := strings.Split(sentence, <span class="string">"\n"</span>)</span><br><span class="line"><span class="keyword">for</span> _, line := <span class="keyword">range</span> lines {</span><br><span class="line">splitWord(line, &resultMap)</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> resultMap</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">splitWord</span><span class="params">(input <span class="type">string</span>, m *[][]<span class="type">string</span>)</span></span> [][]<span class="type">string</span> {</span><br><span class="line"><span class="keyword">var</span> result []<span class="type">string</span></span><br><span class="line"><span class="keyword">var</span> currentWord <span class="type">string</span></span><br><span class="line"><span class="keyword">var</span> intWord <span class="type">string</span></span><br><span class="line"><span class="keyword">var</span> key <span class="type">int</span></span><br><span class="line"><span class="keyword">for</span> _, char := <span class="keyword">range</span> input {</span><br><span class="line"><span class="keyword">if</span> unicode.Is(unicode.Han, char) {</span><br><span class="line"><span class="comment">// 遇到汉字,先保存当前词</span></span><br><span class="line"><span class="keyword">if</span> intWord != <span class="string">""</span> {</span><br><span class="line">key, _ = strconv.Atoi(intWord)</span><br><span class="line">}</span><br><span class="line"><span class="comment">// 如果是汉字,添加到当前词中</span></span><br><span class="line">currentWord += <span class="type">string</span>(char)</span><br><span class="line">} <span class="keyword">else</span> <span class="keyword">if</span> unicode.IsDigit(char) {</span><br><span class="line"><span class="comment">// 遇到数字,先保存当前词</span></span><br><span class="line"><span class="keyword">if</span> currentWord != <span class="string">""</span> {</span><br><span class="line">result = <span class="built_in">append</span>(result, currentWord)</span><br><span class="line">currentWord = <span class="string">""</span></span><br><span class="line">}</span><br><span class="line"><span class="comment">// 将数字作为单独的词添加</span></span><br><span class="line"><span class="keyword">if</span> !unicode.IsSpace(char) {</span><br><span class="line">intWord += <span class="type">string</span>(char)</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"><span class="comment">// 添加最后一个词(如果有的话)</span></span><br><span class="line"><span class="keyword">if</span> currentWord != <span class="string">""</span> {</span><br><span class="line">result = <span class="built_in">append</span>(result, currentWord)</span><br><span class="line">}</span><br><span class="line">(*m)[key<span class="number">-1</span>] = result</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> *m</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>拿到分好词的切片就可以直接打印出来了。这里因为用提取的数字作为key,所以就把切片倒序打印。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">ForLove</span><span class="params">()</span></span> {</span><br><span class="line"><span class="keyword">var</span> s = <span class="string">"喝100杯奶茶\n来99个拥抱\n看98场日落\n要97次接吻\n拍96张照片\n买95朵玫瑰\n去94家餐馆\n看93次大海\n走92条小巷\n打91次雨伞\n要90场牵手\n种89个草莓\n盖88次被子\n递87杯温水\n热86次剩饭\n看85次电影\n做84顿午饭\n切83个水果\n吃82次甜品\n喝81次暖茶\n要80次拥抱\n吃79遍烧烤\n烤78次肉串\n涮77次火锅\n来76次海鲜\n吃75种小吃\n参74场晚宴\n喝73杯喜酒\n吃72次西餐\n尝71颗糖果\n给你70枚吻\n荡69遍秋千\n看68次日出\n躺67次草地\n看66次星空\n闻65次头发\n抱64次肩膀\n吻63次脸颊\n亲62次锁骨\n咬61次耳朵\n有60次相拥\n看59场鬼片\n去58个城市\n吃57桶米花\n逛56个商厦\n打55次的士\n坐54次公交\n等53次地铁\n开52次自驾\n站51遍路灯\n睡50次怀里\n去49个鬼屋\n看48场表演\n逗47只动物\n坐46次飞车\n玩45次激流\n滑44次滑梯\n坐43次飞椅\n转42次陀螺\n吊41次吊索\n吃40次小吃\n捂39次肚子\n揉38次肩膀\n捶37次后背\n捏36次小腿\n暖35次脚丫\n摸34次脑袋\n撮33次肋骨\n挠32次手心\n逗31场大笑\n要30次拥吻\n放29个气球\n钓28只大鱼\n玩27次飞镖\n放26次风筝\n冲25次瀑布\n滑24艘小船\n蹦23场蹦极\n跳22次跳伞\n漂21次河流\n生20次闷气\n骑19次单车\n看18场大雪\n玩17遍飞艇\n去16次森林\n探15个峡谷\n踏14个小溪\n爬13座高山\n看12个沙漠\n坐11次轮船\n写10封情书\n唱9首情歌\n堆8个雪人\n摘7朵野花\n看6场流星\n许5个愿望\n醉4次夜酒\n种3棵玫瑰\n吵2次架\n爱1辈子"</span></span><br><span class="line">param := preParam(s)</span><br><span class="line">summary(param)</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">summary</span><span class="params">(m [][]<span class="type">string</span>)</span></span> {</span><br><span class="line">fmt.Println(<span class="string">"======================================================"</span>)</span><br><span class="line"><span class="keyword">var</span> s <span class="type">string</span></span><br><span class="line"><span class="keyword">for</span> i := <span class="built_in">len</span>(m) - <span class="number">1</span>; i > <span class="number">-1</span>; i-- {</span><br><span class="line">s += m[i][<span class="number">0</span>]</span><br><span class="line">s += strconv.Itoa(i + <span class="number">1</span>)</span><br><span class="line">s += m[i][<span class="number">1</span>]</span><br><span class="line">s += <span class="string">"\n"</span></span><br><span class="line">}</span><br><span class="line">fmt.Println(s)</span><br><span class="line">fmt.Println(<span class="string">"======================================================"</span>)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//======================================================</span></span><br><span class="line"><span class="comment">//喝100杯奶茶</span></span><br><span class="line"><span class="comment">//来99个拥抱</span></span><br><span class="line"><span class="comment">//看98场日落</span></span><br><span class="line"><span class="comment">//要97次接吻</span></span><br><span class="line"><span class="comment">//拍96张照片</span></span><br><span class="line"><span class="comment">//......</span></span><br></pre></td></tr></table></figure><h1 id="随机排序与切片分段"><a href="#随机排序与切片分段" class="headerlink" title="随机排序与切片分段"></a>随机排序与切片分段</h1><p>现在要实现随机排序生成,但是需要注意最后这几个不太适合随机排序不然就成爱2辈子了(</p><p>所以把这么多条做一个切片分段,每十条分一段。有一个类似的算法题用作练习。</p><p><a href="https://leetcode.cn/problems/partition-array-into-disjoint-intervals/description/">LeetCode.915</a></p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">splitSlice</span><span class="params">(slice [][]<span class="type">string</span>, size <span class="type">int</span>)</span></span> [][][]<span class="type">string</span> {</span><br><span class="line"><span class="keyword">var</span> result [][][]<span class="type">string</span></span><br><span class="line"><span class="comment">// 遍历切片并分割</span></span><br><span class="line"><span class="keyword">for</span> i := <span class="number">0</span>; i < <span class="built_in">len</span>(slice); i += size {</span><br><span class="line">end := i + size</span><br><span class="line"><span class="keyword">if</span> end > <span class="built_in">len</span>(slice) {</span><br><span class="line">end = <span class="built_in">len</span>(slice) <span class="comment">// 确保不超出范围</span></span><br><span class="line">}</span><br><span class="line">result = <span class="built_in">append</span>(result, slice[i:end])</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> result</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img src="/img/HaveACup/image2.png" alt="image2.png"></p><p>然后在每个 小分段中做随机排序。同样有一题简单的算法题。</p><p><a href="https://leetcode.cn/problems/shuffle-an-array/description/">LeetCode.384</a></p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">randomMod</span><span class="params">(m [][]<span class="type">string</span>)</span></span> {</span><br><span class="line">fmt.Println(<span class="string">"======================================================"</span>)</span><br><span class="line">sp := splitSlice(m, <span class="number">10</span>)</span><br><span class="line">rand.New(rand.NewSource(time.Now().UnixNano()))</span><br><span class="line"><span class="keyword">for</span> z := <span class="built_in">len</span>(sp) - <span class="number">1</span>; z > <span class="number">0</span>; z-- {</span><br><span class="line">rand.Shuffle(<span class="built_in">len</span>(sp[z]), <span class="function"><span class="keyword">func</span><span class="params">(i, j <span class="type">int</span>)</span></span> {</span><br><span class="line">sp[z][i], sp[z][j] = sp[z][j], sp[z][i]</span><br><span class="line">})</span><br><span class="line">}</span><br><span class="line"><span class="comment">//因为切片分段数据结构改变了,重新写个打印方法</span></span><br><span class="line"><span class="keyword">var</span> c = <span class="number">100</span></span><br><span class="line"><span class="keyword">var</span> resultSlice []<span class="type">string</span></span><br><span class="line"><span class="keyword">for</span> i := <span class="built_in">len</span>(sp) - <span class="number">1</span>; i > <span class="number">-1</span>; i-- {</span><br><span class="line"><span class="keyword">for</span> j := <span class="built_in">len</span>(sp[i]) - <span class="number">1</span>; j > <span class="number">-1</span>; j-- {</span><br><span class="line"><span class="keyword">var</span> s <span class="type">string</span></span><br><span class="line">s += sp[i][j][<span class="number">0</span>]</span><br><span class="line">s += strconv.Itoa(c)</span><br><span class="line">c--</span><br><span class="line">s += sp[i][j][<span class="number">1</span>]</span><br><span class="line">resultSlice = <span class="built_in">append</span>(resultSlice, s)</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">strings.Join(resultSlice, <span class="string">"\n"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> i := <span class="keyword">range</span> resultSlice {</span><br><span class="line">fmt.Println(resultSlice[i])</span><br><span class="line">}</span><br><span class="line">fmt.Println(<span class="string">"======================================================"</span>)</span><br><span class="line">}</span><br><span class="line"><span class="comment">//======================================================</span></span><br><span class="line"><span class="comment">//打100次雨伞</span></span><br><span class="line"><span class="comment">//要99次接吻</span></span><br><span class="line"><span class="comment">//看98次大海</span></span><br><span class="line"><span class="comment">//来97个拥抱</span></span><br><span class="line"><span class="comment">//看96场日落</span></span><br><span class="line"><span class="comment">//.....</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> Go </category>
</categories>
<tags>
<tag> GO </tag>
<tag> CodeTraining </tag>
</tags>
</entry>
<entry>
<title>用Go语言来做一个小游戏吧!</title>
<link href="/posts/1aa03a45/"/>
<url>/posts/1aa03a45/</url>
<content type="html"><![CDATA[<p>为了学习GO语言做了一个简单的2D游戏。游戏中遇到了一些有趣的数学知识,在真实的在代码里体现它之前,还以为会永远用不到这些数学知识。</p><p>GitHub仓库: <a href="https://github.com/KuramiWan/goTraining">goTraining</a></p><h2 id="2D游戏"><a href="#2D游戏" class="headerlink" title="2D游戏"></a>2D游戏</h2><h3 id="对角移动"><a href="#对角移动" class="headerlink" title="对角移动"></a>对角移动</h3><p>设置了游戏角色移动速度为5。在x轴与y轴上这没问题,但是如果要对角移动经过了合速度,实际移动速度就无法恒定。这时候就需要计算出<strong>缩放因子</strong>。</p><p>根据勾股定理:</p><p>V = 5 Vd = squa(Vx<em>Vx + Vy</em>Vy)</p><p>缩放因子 Q = 5 / Vd</p><p>当每一帧移动发生的时候对 Dx 与 Dy进行缩放: Dx = Dx * Q,Dy = Dy * Q。即可保证对角移动速度恒定为V = 5。</p><p>同样可以用数形结合理解,利用三角形等比例缩放。 通过缩放x与y轴恒定一帧内第三边移动距离。</p><h3 id="旋转"><a href="#旋转" class="headerlink" title="旋转"></a>旋转</h3><p>如果游戏角色旋转点不在游戏角色中心。而在周围某一点,比如游戏角色资源的左上角。想要实现角色原地旋转就需要一点小方法调整旋转点。</p><p>在一帧内 平移 → 旋转 → 再平移</p><p>第一次平移将旋转点移动到,原来的游戏角色中心点上。第二次平移将角色复位。</p><p><img src="/img/GoGame/rotate.png" alt="rotate"></p><h2 id="矩形是否重叠"><a href="#矩形是否重叠" class="headerlink" title="矩形是否重叠"></a>矩形是否重叠</h2><p>要计算矩形是否重叠并不简单。要考虑所有的重叠情况。包括边重叠,一共有4种情况(不详细列举)。考虑它的反面要简单的多,也就是矩形不重叠。</p><figure class="highlight jsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//p2x < p3x || p1x > p4x || p1y < p4y || p2y > p3y</span></span><br><span class="line"><span class="comment">//取反</span></span><br><span class="line"><span class="comment">//德·摩根定律转换</span></span><br><span class="line"><span class="comment">//p2y > p3y && p1y < p4y && p2x > p3x && p1x < p4x</span></span><br></pre></td></tr></table></figure><p><img src="/img/GoGame/retan.png" alt="retan"></p><blockquote><p><a href="https://leetcode.cn/problems/rectangle-overlap/description/">LeetCode题目836.矩形重叠</a></p></blockquote><h2 id="3D游戏"><a href="#3D游戏" class="headerlink" title="3D游戏"></a>3D游戏</h2><p>咕咕</p>]]></content>
<categories>
<category> Go </category>
</categories>
<tags>
<tag> GO </tag>
<tag> Game </tag>
</tags>
</entry>
<entry>
<title>HowLinuxWorks随记</title>
<link href="/posts/816097f/"/>
<url>/posts/816097f/</url>
<content type="html"><![CDATA[<p>本文将记录《how linux works》一书中的知识。</p><h1 id="第一章-概述"><a href="#第一章-概述" class="headerlink" title="第一章 概述"></a>第一章 概述</h1><h2 id="Linux层次"><a href="#Linux层次" class="headerlink" title="Linux层次"></a>Linux层次</h2><p>Linux分为用户进程,Linux内核,硬件。<br><img src="https://i.miji.bid/2024/02/26/7142c1515fa66c114e79f963306de349.webp" alt="Linux分层"><br>内核在硬件之上管理硬件系统,是硬件系统和应用程序之间进行通信的接口</p><p>进程指计算机中运行的所有程序,组成了最顶层,称作用户空间或用户进程</p><p>用户进程与内核之间最主要的区别是内核在<strong>内核模式</strong> <em><strong>kernel mode</strong></em>中运行,用户进程在用户模式运行。内核模式中运行不受任何限制访问处理器与内存。那些只有内核可以访问的空间叫做<strong>内存空间</strong> <em><strong>kernel space</strong></em>,反之用户进程可以访问的为<strong>用户空间</strong> <em><strong>user space</strong></em>。<br>一般来说用户进程的影响范围被限制在用户空间内。</p><h2 id="主内存"><a href="#主内存" class="headerlink" title="主内存"></a>主内存</h2><p>与CPU频繁产生读取行为的内存。数据以特定排列的<strong>0与1</strong> <em><strong>bit</strong></em>存储,这被称为<strong>状态</strong> <em><strong>state</strong></em>。我们可以用<strong>状态</strong>的<strong>变化阶段</strong>来描述进程的执行过程(eg. 进程的执行阶段 ,进程正在执行启动任务阶段)。<br><strong>镜像</strong> <em><strong>image</strong></em> 通常表示比特值在内存中的特定物理排列</p><h2 id="内核"><a href="#内核" class="headerlink" title="内核"></a>内核</h2><p>内存负责管理以下四个方面:</p><ul><li>进程:决定哪个进程可以使用CPU</li><li>内存:内存分配,管理进程间的共享内存与空闲内存</li><li>设备驱动程序:作为硬件系统和进程之间的接口</li><li>系统调用和支持: 进程使用系统调用和进程通信</li></ul><h3 id="进程管理"><a href="#进程管理" class="headerlink" title="进程管理"></a>进程管理</h3><p>进程轮流使用CPU实现同时运行多个进程,被称作<strong>多任务执行</strong>。CPU从执行一个进程切换到执行另一个进程就叫做<strong>上下文切换</strong> <em><strong>context swich</strong></em></p><ol><li>CPU停止A进程,由内核接管CPU控制权</li><li>内核记录下但前CPU和内存的<strong>状态</strong>信息,在恢复进程时使用</li><li>内核执行上个时间段内被悬置的任务(输入输出,磁盘读写)</li><li>内核准备执行下一个进程,从准备就绪的进程中选择一个执行</li><li>内核为B进程准备CPU与内存</li><li>内核将新进程执行时间段通知CPU</li><li>内核将CPU切换至用户模式,将CPU控制权移交给新进程</li></ol><blockquote><p>内核在什么时候运行的?<br>在上下文切换时的时间段间隙中运行的</p></blockquote><h3 id="内存管理"><a href="#内存管理" class="headerlink" title="内存管理"></a>内存管理</h3><p>内核在上下文切换过程中管理内存,内核要保证以下条件</p><ul><li>内核自己的专有内存空间</li><li>每个用户进程的专有空间</li><li>用户进程之间的共享空间</li><li>用户进程的某些内存空间可以是只读</li><li><strong>交换空间</strong> <em><strong>swap space</strong></em> 扩展出比实际内存容量更大的内存空间</li></ul><p> <strong>MMU</strong> <strong>内存管理单元</strong> <em><strong>Memory Management Unit</strong></em><br> 让进程不是直接访问内存的实际物理地质,而是通过MMU截获进程的访问请求通过<strong>内存映射表</strong>将虚拟地址转换为世纪物理地址。内核将会维护这张表</p><blockquote><p>内存映射地址使用<strong>页表</strong> <em><strong>page table</strong></em> 实现</p></blockquote><h3 id="驱动程序"><a href="#驱动程序" class="headerlink" title="驱动程序"></a>驱动程序</h3><p>设备驱动程序在传统意义上来说也是内核的一部分,作用都是为用户进程提供统一的结构,使用硬件设备。</p><h3 id="系统调用和系统支持"><a href="#系统调用和系统支持" class="headerlink" title="系统调用和系统支持"></a>系统调用和系统支持</h3><p><strong>系统调用</strong> <em><strong>system call</strong></em><br>有时候用户进程需要执行一些不方便或是无法完成的工作。 打开,读取,写文件这些操作都涉及系统调用。<br>fork(): 当进程调用fork时,内核创建一个和该进程几乎一样的副本<br>exec(): 当进程调用exec(program) 内核启动program来替换当前进程<br>除了init外,Linux中所有的用户进程都是通过fork()来启动的。除了创建现有进程的副本外,多数情况下你还可以使用exec() 来启动新的进程。<br>当你在terminal中输入ls时会发生什么?<br>终端窗口中的shell调用fork()创建一个shell副本,这时候有了两个一样的shell进程,然后该副本调用exec(ls) 来运行ls。</p><p>内核还为用户进程提供了许多功能,比如虚拟设备。虚拟设备是用软件模式出的硬件设备,技术上来说这并不需要存在与内核中,但是就实现难度来说,放在内核中要小的多,比如<strong>岁技术生成器</strong> (/dev/random)</p><h2 id="用户空间"><a href="#用户空间" class="headerlink" title="用户空间"></a>用户空间</h2><p>不同的用户进程被分配了独立的用户空间执行了不同的任务。</p><h2 id="用户"><a href="#用户" class="headerlink" title="用户"></a>用户</h2><p>Linux内核继承了UNIX的用户概念。早期还为产生PC这一概念时,多终端使用统一台设备,会有多个用户。<br>内核通过用户ID管理用户。每一个用户进程都有一个用户所有者。管理员用户即root拥有超级权限。</p><blockquote><p>虽然root用户权限很高但是还是在用户模式而非内核模式</p></blockquote><h1 id="第二章-基础命令"><a href="#第二章-基础命令" class="headerlink" title="第二章 基础命令"></a>第二章 基础命令</h1><p>Linux 默认 Shell是最初的Bourne Shell的增强版,称之为<strong>bash</strong> <em><strong>Bourne-again shell</strong></em></p><h2 id="标准输入输出"><a href="#标准输入输出" class="headerlink" title="标准输入输出"></a>标准输入输出</h2><p>进程向输入流中读取数据向输出流中写出数据。<br>在终端中输入</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat</span><br></pre></td></tr></table></figure><p>当只输入cat时就从Linux内核提供的默认标准输入流中获得输入数据,这是运行cat命令的终端就成了标准输入。这时候你输入任意字符就会在回显出来。<br><code>CRTL+D</code> 终止当前终端的标准输入并种植命令<br><code>CRTL+C</code> 种植当前进程的运行,无论是否有输入输出</p><p>标准输出也与之类似。在cat运行时标准输出就和该终端建立了连接,所以看到了回显</p><p>标准输入和标准输出简写为stdin 和 stdout。 很多命令和cat一样如果不指定输入文件就从标准输入获得输入。 而输出有点不同,有部分命令会将数据直接输出到文件。<br>Linux 中 <code>.</code> 代表当前目录 eg. <code>./mydir/</code> ..代表上级目录eg. <code>cd ../../usr</code></p><h3 id="通配符"><a href="#通配符" class="headerlink" title="通配符"></a>通配符</h3><p>shell中 <code>*</code> 代表仍以字符和数字<br>Shell 根据通配符匹配文件, Shell 将命令中的参数替换为实际的文件名,这个过程叫做<strong>展开</strong></p><ul><li>at* 展开为所有以at结尾文件名;</li><li>*at 展开为所有以at开头文件名;</li><li><em>at</em> 展开为所有包含at文件名;</li></ul><p>使用<code>?</code> 匹配任意一个字符 eg. <code>b?at</code> 匹配 <code>boat</code> 和 <code>brat</code></p><blockquote><p>如果通配符没有匹配的文件名shell就不会进行展开</p></blockquote><blockquote><p>如果不想要展开可以使用 <code>'*'</code> 转义</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line">//打印</span><br><span class="line">echo Hello there</span><br><span class="line">//查看文件内容</span><br><span class="line">cat /etc/passwd</span><br><span class="line">//查看多个文件</span><br><span class="line">cat file1 file2</span><br><span class="line">//查看文件列表信息</span><br><span class="line">ls -l</span><br><span class="line">//隐藏文件</span><br><span class="line">ls -a</span><br><span class="line">// 复制文件</span><br><span class="line">cp file file1</span><br><span class="line">// 多个文件复制到dir</span><br><span class="line">cp file1 .... fileN dir</span><br><span class="line">// 重命名</span><br><span class="line">mv file file1</span><br><span class="line">// 移动多个文件</span><br><span class="line">mv file1 .... fileN dir</span><br><span class="line">//创建文件</span><br><span class="line">touch file</span><br><span class="line">//删除文件</span><br><span class="line">rm file</span><br><span class="line">//移动当前目录</span><br><span class="line">cd dir</span><br><span class="line">//创建文件夹</span><br><span class="line">mkdir dir</span><br><span class="line">//产出文件夹,前提空文件夹</span><br><span class="line">rmdir dir</span><br><span class="line">// grep -i 不区分大小写 -v 反转匹配,所有不匹配的 egrep 等同于 grep -E 启用正则表达式</span><br><span class="line">// .* 匹配任意多个字符</span><br><span class="line">// . 匹配任意一个字符</span><br><span class="line">在passwd文件中查找root</span><br><span class="line">grep root /etc/passwd</span><br><span class="line">//more命令的增强版 空格查看下一屏 B查看上一屏 Q 退出 /word 向下匹配word ?word向上匹配</span><br><span class="line">less file</span><br><span class="line">//显示当前目录</span><br><span class="line">pwd</span><br><span class="line">//比较文件</span><br><span class="line">diff file1 file2</span><br><span class="line">//文件详细信息</span><br><span class="line">file file</span><br><span class="line">//在 dir目录下查找file文件</span><br><span class="line">find dir -name file -print</span><br><span class="line">//在索引中查找,Linux内核维护着文件索引,定期更新,如果你创建了一个新的文件,它可能不在索引里</span><br><span class="line">locate dir -name file -print</span><br><span class="line">//查看文件头部</span><br><span class="line">head</span><br><span class="line">//查看文件尾部</span><br><span class="line">tail</span><br><span class="line">//按照字母数字顺序排序 -r 反向排序</span><br><span class="line">sort</span><br><span class="line">//重定向符将输出重定向到文件eg. cat README.md > readme.out</span><br><span class="line">command > file</span><br><span class="line">//输出不覆盖加入到文件末尾</span><br><span class="line">command >> file</span><br></pre></td></tr></table></figure><h2 id="环境变量和Shell变量"><a href="#环境变量和Shell变量" class="headerlink" title="环境变量和Shell变量"></a>环境变量和Shell变量</h2><p>通过<code>$</code> 使用声明过的Shell变量<br>环境变量和Shell变量最大的区别是Shell变量只能被当前Shell所使用</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">//shell 变量</span><br><span class="line">STUFF=blah</span><br><span class="line">echo $STUFF</span><br><span class="line">//环境变量</span><br><span class="line">export STUFF</span><br></pre></td></tr></table></figure><h2 id="命令路径"><a href="#命令路径" class="headerlink" title="命令路径"></a>命令路径</h2><p>与环境变量相似,在路径被加入命令路径下之后,其下的文件执行可以在任意路径中使用命令执行而不需要指定路径。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">echo $PATH</span><br><span class="line">/home/kurami/.nvm/versions/node/v16.20.2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/kurami/.local/share/JetBrains/Toolbox/scripts</span><br><span class="line">//添加命令路径</span><br><span class="line">PATH=$PATH:dir</span><br></pre></td></tr></table></figure><h2 id="命令行编辑"><a href="#命令行编辑" class="headerlink" title="命令行编辑"></a>命令行编辑</h2><p>一些快捷方式帮助你比箭头更方便的编辑</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">CTRL+B 左移</span><br><span class="line">CTRL+F 右移</span><br><span class="line">CTRL+P 查看上一条命令</span><br><span class="line">CTRL+N 查看下一条命令</span><br><span class="line">CTRL+A 移动光标到行首 home</span><br><span class="line">CTRL+E 移动光标到行尾 end</span><br><span class="line">CTRL+W 删除前一个词 </span><br><span class="line">CTRL+U 删除从光标至行首内容</span><br><span class="line">CTRL+K 删除从光标至行尾内容</span><br><span class="line">CTRL+Y 粘贴已删除文本</span><br></pre></td></tr></table></figure><h2 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h2><p><img src="https://ice.frostsky.com/2024/03/20/f17658bc5e49ffc255e5a18901ca89b5.png" alt="Linux目录结构"></p><ul><li>/bin 存放可执行文件,包括大部分基础的Unix命令大部分是由C编译器创建的二进制文件</li><li>/dev 设备文件</li><li>/etc 系统配置文件</li><li>/home 个人目录</li><li>/lib 共可执行文件使用的代码库</li><li>/proc 存放系统相关信息如当前运行的进程和内核信息</li><li>/sys 类似/proc</li><li>/sbin 可执行的系统文件,用来管理系统许多命令使用由root用户银杏</li><li>/tmp 临时文件 很多系统会在启动时清空该文件夹</li><li>/usr 存放许多Linux 系统文件</li><li>/var 存放运行时信息的地方 如系统直至,用户信息,缓存和其他信息</li></ul>]]></content>
<categories>
<category> Linux </category>
</categories>
<tags>
<tag> Linux </tag>
</tags>
</entry>
<entry>
<title>全栈测试随记</title>
<link href="/posts/bdbed721/"/>
<url>/posts/bdbed721/</url>
<content type="html"><![CDATA[<p>本文将记录关于《Full Stack Testing》这本书中的诸多方法论与测试技巧</p><h1 id="手动探索测试"><a href="#手动探索测试" class="headerlink" title="手动探索测试"></a>手动探索测试</h1><p>手动探索性测试一般处于开发后进行,探索性测试强调所有三个角度(业务需求,技术实现细节,最终用户需求)结合起来,并从这些所有角度去挑战在过去业务角度,功能开发角度中被认为对的事情。相较于传统手动测试,完成特定测试任务以满足某一需求文档中的验收标注,手动探索测试更为自由,更为全局。手动探索测试在特定的测试环境中随意干预各种应用程序组件,例如数据库,服务或者后台进程。</p><h2 id="探索性测试框架"><a href="#探索性测试框架" class="headerlink" title="探索性测试框架"></a>探索性测试框架</h2><h3 id="等价类划分"><a href="#等价类划分" class="headerlink" title="等价类划分"></a>等价类划分</h3><p>假如有一个正数的输入值x,有x小于500,x在500 与1500之间,大于1500,针对三种情况分别有三个不同的策略。如何进行测试?</p><p>可以划分为三个等价类 {0-500,500-1500,1500- },只需要在其区间内各区三个数就可覆盖所有情况。</p><h3 id="边界值分析"><a href="#边界值分析" class="headerlink" title="边界值分析"></a>边界值分析</h3><p>边界值分析法是等价类的扩展方法。它将类之间模糊不清的边界值也纳入测试,{0,1,500,501,1500,1501}</p><h3 id="状态转换"><a href="#状态转换" class="headerlink" title="状态转换"></a>状态转换</h3><p>在程序的行为根据历史记录发生变化时可以使用状态转换将状态过程可视化。比如登录三次失败三次账号锁定。</p><p><img src="https://i.miji.bid/2024/01/31/6d46e770978a11be346d7fbd3da39c9a.webp" alt="状态转换"></p><h3 id="决策表"><a href="#决策表" class="headerlink" title="决策表"></a>决策表</h3><p>在面对逻辑关系(And&or)时将可能结果列出。类似真值表</p><h3 id="因果图"><a href="#因果图" class="headerlink" title="因果图"></a>因果图</h3><p>直接画出因果关系。<br><img src="https://i.miji.bid/2024/01/31/1a3f9881383f43d7582d1217ad679242.webp" alt="因果图"></p><h3 id="成对测试"><a href="#成对测试" class="headerlink" title="成对测试"></a>成对测试</h3><p>或许在测试中会遇到多个条件组合需要测试的情况,在复杂情况下如果通过穷举则非常困难。比如目前有三个条件每一个条件都有两种情况 A(1,2), B(1,2), C(1,2)。我们需要测试 2 * 2 * 2 种情况才能完全覆盖。<br>我们如何测试单因子和双因子错误率?</p><p>单错误因子情况下假设 A(1) 为错误因子。我们<strong>至少</strong>需要 {A(1),B(1),C(1)} & {A(2),B(1),C(1)} ,两组数据就能测出。</p><p>双错误因子情况下假设 {A(1),B(1)} 为错误因子。我们<strong>至少</strong>需要 {A(1),B(1),C(1)} & {A(1),B(1),C(2)} & {A(1),B(2),C(1)} & {A(2),B(1),C(1)} 四组数据才能测出。</p><p>而三因子情况下我们需要全部8组数据才能测出。</p><p>研究发现单因子和双因子导致错误率在80%左右,而三因子错误率在20%。 所以只需要测试单因子与双因子情况就能基本覆盖错误。同时减少50%的测试量。<br><a href="https://pairwise.teremokgames.com/">成对测试算法工具</a></p><h3 id="采样"><a href="#采样" class="headerlink" title="采样"></a>采样</h3><p>随机抽样检查</p><h3 id="经验法"><a href="#经验法" class="headerlink" title="经验法"></a>经验法</h3><p>根据我的经验,以下是经常出现的几种类型的错误:</p><ul><li><p>缺少对无效/空白输入值的验证,并且缺少指导用户更正输入的适当错误消息</p></li><li><p>数据验证、技术和业务错误返回的 HTTP 状态代码不明确</p></li><li><p>特定于域、数据类型、状态等的未处理的边界条件</p></li><li><p>UI 端未处理的技术错误,例如服务器关闭、响应超时等</p></li><li><p>转换、数据刷新和导航期间的 UI 问题(例如抖动和残留)</p></li><li><p>SQL 关键字_like_和_equals_可以互换使用,完全改变结果</p></li><li><p>未清除的缓存和未定义的会话超时</p></li><li><p>当用户单击浏览器中的后退按钮时重新发布请求</p></li><li><p>从不同操作系统平台上传文件时缺少文件格式验证</p></li></ul><h2 id="探索功能"><a href="#探索功能" class="headerlink" title="探索功能"></a>探索功能</h2><p><strong>对一个全新的应用进行测试时,你应该想到哪些测试思路?</strong></p><h3 id="功能性用户流程"><a href="#功能性用户流程" class="headerlink" title="功能性用户流程"></a>功能性用户流程</h3><p>测试用户完整使用应用的流程,在这个测试可以使用上文所介绍的测试框架。<br><strong>重复该流程</strong><br>在完成一次测试后不刷新状态,重新测试。<br><strong>多用户流程</strong><br>多用户并发操作时会发生什么?</p><h3 id="失败和错误处理"><a href="#失败和错误处理" class="headerlink" title="失败和错误处理"></a>失败和错误处理</h3><p>当服务器返回错误的信息,前端UI应该如何处理。</p><h3 id="用户界面的观感"><a href="#用户界面的观感" class="headerlink" title="用户界面的观感"></a>用户界面的观感</h3><p>不是指用户界面的设计美感,而是关于用户体验方面,比如某一描述性文字是否有足够的空间显示延迟时的等待体验,图片的质量等等方面。</p><h3 id="跨职能方面"><a href="#跨职能方面" class="headerlink" title="跨职能方面"></a>跨职能方面</h3><p>安全,性能,可访问性,身份验证,授权,隐私,可审查性等等方面。</p><h2 id="手动探索测试策略"><a href="#手动探索测试策略" class="headerlink" title="手动探索测试策略"></a>手动探索测试策略</h2><p>对于一个陌生的应用可以从一下五个方面思考测试策略。</p><h3 id="用户角色"><a href="#用户角色" class="headerlink" title="用户角色"></a>用户角色</h3><p>一个应用可能有不同的角色,扮演不同的角色去了解应用。</p><h3 id="领域"><a href="#领域" class="headerlink" title="领域"></a>领域</h3><p>每一个行业,每一个业务领域都有独特的工作流程,你需要了解应用的领域知识。</p><h3 id="业务重点"><a href="#业务重点" class="headerlink" title="业务重点"></a>业务重点</h3><p>在复杂业务上,考虑项目的可扩展性与项目整体。</p><h3 id="基础设施和配置"><a href="#基础设施和配置" class="headerlink" title="基础设施和配置"></a>基础设施和配置</h3><p>了解实际部署应用机器的如构件的各项配置是必要的,它能帮你观察是否出现了异常的情况。</p><h3 id="组织架构"><a href="#组织架构" class="headerlink" title="组织架构"></a>组织架构</h3><p>组织架构也是测试的切入点。例如,如果架构涉及 Web 服务,您可能需要对 API 执行探索性测试,而不仅仅是探索 UI。同样,如果应用程序涉及事件流,那么探索异步通信的案例就变得很重要。</p><h2 id="测试工具"><a href="#测试工具" class="headerlink" title="测试工具"></a>测试工具</h2><h3 id="思维导图可能会帮到你"><a href="#思维导图可能会帮到你" class="headerlink" title="思维导图可能会帮到你"></a>思维导图可能会帮到你</h3><p><img src="https://i.miji.bid/2024/01/31/d05a16d7f0bbbc5cf217ef7547090630.webp" alt="思维导图"></p><h3 id="Apifox"><a href="#Apifox" class="headerlink" title="Apifox"></a><a href="https://apifox.com/">Apifox</a></h3><p>集接口测试,在线mock,环境变量,脚本于一体的强大测试工具,缺点是强制登录。</p><h3 id="测试环境卫生"><a href="#测试环境卫生" class="headerlink" title="测试环境卫生"></a>测试环境卫生</h3><h3 id="共享测试环境与专用测试环境"><a href="#共享测试环境与专用测试环境" class="headerlink" title="共享测试环境与专用测试环境"></a>共享测试环境与专用测试环境</h3><p>一个团队一个测试环境。</p><h3 id="测试数据卫生"><a href="#测试数据卫生" class="headerlink" title="测试数据卫生"></a>测试数据卫生</h3><p>测试数据属于权限范围测试人员的行为,他们应该遵循某些实践,以确保他们不会无意中破坏自己的探索。特别是,在同一部署中继续测试新功能时,请注意过时的数据和配置。避免此类复杂情况的建议是,每当开始新的用户故事时,就部署新的构建(假设新的部署将清除旧的数据和配置并将应用程序恢复到新状态)。另一种选择是为每个用户故事(例如新用户)创建一组新的测试数据,而不是探索可能处于不同状态的现有用户。</p><p>当有数百个链接表时,测试数据创建可能会很复杂。然后,一个选项是让新部署删除旧数据并将其替换为一组标准测试数据,或者让 SQL 脚本创建适当的新测试数据作为部署的一部分。</p><h3 id="自治团队"><a href="#自治团队" class="headerlink" title="自治团队"></a>自治团队</h3><p>团队成员可能没有登录凭据或更新配置、查看应用程序日志或设置存根所需的权限;要执行此类操作,他们需要向 DevOps 或系统维护团队请求帮助。这在探索性测试期间尤其令人沮丧,因为测试人员可能需要访问所有应用程序组件。确保团队是自主的并且能够访问所需的一切,这将减少由于外部依赖性而导致的延迟并实现顺利交付。</p>]]></content>
<categories>
<category> 测试 </category>
</categories>
<tags>
<tag> 测试 </tag>
<tag> 全栈测试 </tag>
<tag> 方法论 </tag>
</tags>
</entry>
<entry>
<title>混沌工程随记</title>
<link href="/posts/9a583f9/"/>
<url>/posts/9a583f9/</url>
<content type="html"><![CDATA[<p>混沌工程并不是在生产环境中搞破坏。搞破坏很容易但完成下述事情很难:减小爆炸半径,对安全性进行批判性思考,确定漏洞是否值得修复,决定是否应该进行实验。<br>寻找做对的地方比寻找做错的地方提供的信息多得多,因为对于复杂系统而言,故障可能是因为熵增而导致的系统性错误,这些并不能被预测到。而混沌工程通过实验认识到系统的属性信息,从而可以通过测试的方法规避掉错误,让团队拥有更好韧性。 对与让系统更加健壮而言,一味的冗余只会掩盖问题的存在,同时冗余的同时引入了故障,发生了熵增。</p>]]></content>
<categories>
<category> 工程 </category>
</categories>
<tags>
<tag> 工程 </tag>
<tag> 混沌工程 </tag>
<tag> 测试 </tag>
</tags>
</entry>
</search>