mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-02-03 23:40:14 +08:00
Merge remote-tracking branch 'LCTT/master'
This commit is contained in:
commit
dec6a0a9d3
111
sources/talk/20190926 How to contribute to GitLab.md
Normal file
111
sources/talk/20190926 How to contribute to GitLab.md
Normal file
@ -0,0 +1,111 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (How to contribute to GitLab)
|
||||
[#]: via: (https://opensource.com/article/19/9/how-contribute-gitlab)
|
||||
[#]: author: (Ray Paik https://opensource.com/users/rpaikhttps://opensource.com/users/barkerd427)
|
||||
|
||||
How to contribute to GitLab
|
||||
======
|
||||
Help the community by contributing to code, documentation, translations,
|
||||
user experience design, and more.
|
||||
![Woman programming][1]
|
||||
|
||||
I think many people are familiar with GitLab—the company or the software. What many may not realize is that GitLab is also an open source community that started with this [first commit][2] from our co-founder [Dmitriy Zaporozhet][3] in 2011. As a matter of fact, we have [more than 2,000 contributors][4] from the wider community who have contributed to GitLab.
|
||||
|
||||
The wider community contributions span code, documentation, translations, user experience design, etc. If you are interested in open source and in contributing to a complete DevOps platform, I'd like you to consider joining the GitLab community.
|
||||
|
||||
You can find things that you can start contributing to by looking at issues with the "[Accepting merge requests" label sorted by weight][5]. Low-weight issues will be easier to accomplish. If you find an issue that you're interested in working on, be sure to add a comment on the issue saying that you'd like to work on this, and verify that no one is already working on it. If you cannot find an issue that you are interested in but have an idea for a contribution (e.g., bug fixes, documentation update, new features, etc.), we encourage you to open a new issue or even [open a merge request][6] (MR) to start working with reviewers or other community members.
|
||||
|
||||
If you are interested, here are the different areas at GitLab where you can contribute and how you can get started.
|
||||
|
||||
### Development
|
||||
|
||||
Whether it's fixing bugs, adding new features, or helping with reviews, GitLab is a great open source community for developers from all backgrounds. Many contributors have started contributing to GitLab development without being familiar with languages like Ruby. You can follow the steps below to start contributing to GitLab development:
|
||||
|
||||
1. For GitLab development, you should download and set up the [GitLab Development Kit][7]. The GDK README has instructions on how you can get started.
|
||||
2. [Fork the GitLab project][8] that you want to contribute to.
|
||||
3. Add the feature or fix the bug you want to work on.
|
||||
4. If you work on a feature change that impacts users or admins, please also [update the documentation][9].
|
||||
5. [Open an MR][6] to merge your code and its documentation. The earlier you open an MR, the sooner you can get feedback. You can mark your MR as a [Work in Progress][10] so that people know that you're not done yet.
|
||||
6. Add tests, if needed, as well as a [changelog entry][11] so you can be credited for your work.
|
||||
7. Make sure the test suite is passing.
|
||||
8. Wait for a reviewer. A "Community contribution" label will be added to your MR, and it will be triaged within a few days and a reviewer notified. You may need multiple reviews/iterations depending on the size of the change. If you don't hear from anyone in several days, feel free to mention the Merge Request Coaches by typing **@gitlab-org/coaches** in a comment.
|
||||
|
||||
|
||||
|
||||
### Documentation
|
||||
|
||||
Contributing to documentation is a great way to get familiar with the GitLab development process and to meet reviewers and other community members. From fixing typos to better organizing our documentation, you will find many areas where you can contribute. Here are the recommended steps for people interested in helping with documentation:
|
||||
|
||||
1. Visit [https://docs.gitlab.com][12] for the latest GitLab documentation.
|
||||
2. If you find a page that needs improvement, click the "Edit this page" link at the bottom of the page, fork the project, and modify the documentation.
|
||||
3. Open an MR and follow the [branch-naming convention for documentation][13] so you can speed up the continuous integration process.
|
||||
4. Wait for a reviewer. A "Community contribution" label will be added to your MR and it will be triaged within a few days and a reviewer notified. If you don't hear from a reviewer in several days, feel free to mention **@gl-docsteam** in a comment.
|
||||
|
||||
|
||||
|
||||
You may also want to reference [GitLab Documentation Guidelines][9] as you contribute to documentation.
|
||||
|
||||
### Translation
|
||||
|
||||
GitLab is being translated into more than 35 languages, and this is driven primarily by wider community members. If you speak another language, you can join more than 1,500 community members who are helping translate GitLab.
|
||||
|
||||
The translation is managed at <https://translate.gitlab.com> using [CrowdIn][14]. First, a phrase (e.g., one that appears in the GitLab user interface or in error messages) needs to be internationalized before it can be translated. The internationalized phrases are then made available for translations on <https://translate.gitlab.com>. Here's how you can help us speak your language:
|
||||
|
||||
1. Log into <https://translate.gitlab.com> (you can use your GitLab login).
|
||||
2. Find a language you'd like to contribute to.
|
||||
3. Improve existing translations, vote on new translations, and/or contribute new translations to your given language.
|
||||
4. Once your translation is approved, it will be merged into future GitLab releases.
|
||||
|
||||
|
||||
|
||||
### UX design
|
||||
|
||||
In order to help make a product that is easy to use and built for a diverse group of people, we welcome contributions from the wider community. You can help us better understand how you use GitLab and your needs as you work with the GitLab UX team members. Here's how you can get started:
|
||||
|
||||
1. Visit the [https://design.gitlab.com][15] for an overview of GitLab's open source Design System. You may also find the [Get Started guide][16] to be helpful.
|
||||
2. Choose an [issue][17] to work on. If you can't find an issue that you are interested in, you can open a new issue to start a conversation and get early feedback.
|
||||
3. Create an MR to make changes that reflect the issue you're working on.
|
||||
4. Wait for a reviewer. A "Community contribution" label will be added to your MR, and it will be triaged within a few days and a reviewer notified. If you don't hear from anyone in several days, feel free to mention **@gitlab-com/gitlab-ux** in a comment.
|
||||
|
||||
|
||||
|
||||
### Getting help
|
||||
|
||||
If you need any help while contributing to GitLab, you can refer to the [Getting Help][18] section on our Contribute page for available resources. One thing I want to emphasize is that you should not feel afraid to [mention][19] people at GitLab in issues or MRs if you have any questions or if you feel like someone has not been responsive. GitLab team members should be responsive to other community members whether they work at GitLab or not.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/9/how-contribute-gitlab
|
||||
|
||||
作者:[Ray Paik][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/rpaikhttps://opensource.com/users/barkerd427
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/programming-code-keyboard-laptop-music-headphones.png?itok=EQZ2WKzy (Woman programming)
|
||||
[2]: https://gitlab.com/gitlab-org/gitlab-ce/commit/9ba1224867665844b117fa037e1465bb706b3685
|
||||
[3]: https://about.gitlab.com/company/team/#dzaporozhets
|
||||
[4]: https://contributors.gitlab.com
|
||||
[5]: https://gitlab.com/groups/gitlab-org/-/issues?assignee_id=None&label_name%5B%5D=Accepting+merge+requests&scope=all&sort=weight&state=opened&utf8=%E2%9C%93
|
||||
[6]: https://docs.gitlab.com/ee/gitlab-basics/add-merge-request.html
|
||||
[7]: https://gitlab.com/gitlab-org/gitlab-development-kit
|
||||
[8]: https://docs.gitlab.com/ee/workflow/forking_workflow.html#creating-a-fork
|
||||
[9]: https://docs.gitlab.com/ee/development/documentation/
|
||||
[10]: https://docs.gitlab.com/ee/user/project/merge_requests/work_in_progress_merge_requests.html
|
||||
[11]: https://docs.gitlab.com/ee/development/changelog.html
|
||||
[12]: https://docs.gitlab.com/
|
||||
[13]: https://docs.gitlab.com/ee/development/documentation/index.html#branch-naming
|
||||
[14]: https://crowdin.com/
|
||||
[15]: https://design.gitlab.com/
|
||||
[16]: https://design.gitlab.com/contribute/get-started/
|
||||
[17]: https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/issues
|
||||
[18]: https://about.gitlab.com/community/contribute/#getting-help
|
||||
[19]: https://docs.gitlab.com/ee/user/group/subgroups/#mentioning-subgroups
|
@ -1,5 +1,5 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
|
@ -1,138 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Introduction to the Linux chgrp and newgrp commands)
|
||||
[#]: via: (https://opensource.com/article/19/9/linux-chgrp-and-newgrp-commands)
|
||||
[#]: author: (Alan Formy-Duval https://opensource.com/users/alanfdosshttps://opensource.com/users/sethhttps://opensource.com/users/alanfdosshttps://opensource.com/users/seth)
|
||||
|
||||
Introduction to the Linux chgrp and newgrp commands
|
||||
======
|
||||
The chgrp and newgrp commands help you manage files that need to
|
||||
maintain group ownership.
|
||||
![Penguins walking on the beach ][1]
|
||||
|
||||
In a recent article, I introduced the [**chown** command][2], which is used for modifying ownership of files on systems. Recall that ownership is the combination of the user and group assigned to an object. The **chgrp** and **newgrp** commands provide additional help for managing files that need to maintain group ownership.
|
||||
|
||||
### Using chgrp
|
||||
|
||||
The **chgrp** command simply changes the group ownership of a file. It is the same as the **chown :<group>** command. You can use:
|
||||
|
||||
|
||||
```
|
||||
`$chown :alan mynotes`
|
||||
```
|
||||
|
||||
or:
|
||||
|
||||
|
||||
```
|
||||
`$chgrp alan mynotes`
|
||||
```
|
||||
|
||||
#### Recursive
|
||||
|
||||
A few additional arguments to chgrp can be useful at both the command line and in a script. Just like many other Linux commands, chgrp has a recursive argument, **-R**. You will need this to operate on a directory and its contents recursively, as I'll demonstrate below. I added the **-v** (**verbose**) argument so chgrp tells me what it is doing:
|
||||
|
||||
|
||||
```
|
||||
$ ls -l . conf
|
||||
.:
|
||||
drwxrwxr-x 2 alan alan 4096 Aug 5 15:33 conf
|
||||
|
||||
conf:
|
||||
-rw-rw-r-- 1 alan alan 0 Aug 5 15:33 conf.xml
|
||||
# chgrp -vR delta conf
|
||||
changed group of 'conf/conf.xml' from alan to delta
|
||||
changed group of 'conf' from alan to delta
|
||||
```
|
||||
|
||||
#### Reference
|
||||
|
||||
A reference file (**\--reference=RFILE**) can be used when changing the group on files to match a certain configuration or when you don't know the group, as might be the case when running a script. You can duplicate another file's group (**RFILE**), referred to as a reference file. For example, to undo the changes made above (recall that a dot [**.**] refers to the present working directory):
|
||||
|
||||
|
||||
```
|
||||
`$ chgrp -vR --reference=. conf`
|
||||
```
|
||||
|
||||
#### Report changes
|
||||
|
||||
Most commands have arguments for controlling their output. The most common is **-v** to enable verbose, and the chgrp command has a verbose mode. It also has a **-c** (**\--changes**) argument, which instructs chgrp to report only when a change is made. Chgrp will still report other things, such as if an operation is not permitted.
|
||||
|
||||
The argument **-f** (**\--silent**, **\--quiet**) is used to suppress most error messages. I will use this argument and **-c** in the next section so it will show only actual changes.
|
||||
|
||||
#### Preserve root
|
||||
|
||||
The root (**/**) of the Linux filesystem should be treated with great respect. If a command mistake is made at this level, the consequences can be terrible and leave a system completely useless. Particularly when you are running a recursive command that will make any kind of change—or worse, deletions. The chgrp command has an argument that can be used to protect and preserve the root. The argument is **\--preserve-root**. If this argument is used with a recursive chgrp command on the root, nothing will happen and a message will appear instead:
|
||||
|
||||
|
||||
```
|
||||
[root@localhost /]# chgrp -cfR --preserve-root a+w /
|
||||
chgrp: it is dangerous to operate recursively on '/'
|
||||
chgrp: use --no-preserve-root to override this failsafe
|
||||
```
|
||||
|
||||
The option has no effect when it's not used in conjunction with recursive. However, if the command is run by the root user, the permissions of **/** will change, but not those of other files or directories within it:
|
||||
|
||||
|
||||
```
|
||||
[alan@localhost /]$ chgrp -c --preserve-root alan /
|
||||
chgrp: changing group of '/': Operation not permitted
|
||||
[root@localhost /]# chgrp -c --preserve-root alan /
|
||||
changed group of '/' from root to alan
|
||||
```
|
||||
|
||||
Surprisingly, it seems, this is not the default argument. The option **\--no-preserve-root** is the default. If you run the command above without the "preserve" option, it will default to "no preserve" mode and possibly change permissions on files that shouldn't be changed:
|
||||
|
||||
|
||||
```
|
||||
[alan@localhost /]$ chgrp -cfR alan /
|
||||
changed group of '/dev/pts/0' from tty to alan
|
||||
changed group of '/dev/tty2' from tty to alan
|
||||
changed group of '/var/spool/mail/alan' from mail to alan
|
||||
```
|
||||
|
||||
### About newgrp
|
||||
|
||||
The **newgrp** command allows a user to override the current primary group. newgrp can be handy when you are working in a directory where all files must have the same group ownership. Suppose you have a directory called _share_ on your intranet server where different teams store marketing photos. The group is **share**. As different users place files into the directory, the files' primary groups might become mixed up. Whenever new files are added, you can run **chgrp** to correct any mix-ups by setting the group to **share**:
|
||||
|
||||
|
||||
```
|
||||
$ cd share
|
||||
ls -l
|
||||
-rw-r--r--. 1 alan share 0 Aug 7 15:35 pic13
|
||||
-rw-r--r--. 1 alan alan 0 Aug 7 15:35 pic1
|
||||
-rw-r--r--. 1 susan delta 0 Aug 7 15:35 pic2
|
||||
-rw-r--r--. 1 james gamma 0 Aug 7 15:35 pic3
|
||||
-rw-rw-r--. 1 bill contract 0 Aug 7 15:36 pic4
|
||||
```
|
||||
|
||||
I covered **setgid** mode in my article on the [**chmod** command][3]. This would be one way to solve this problem. But, suppose the setgid bit was not set for some reason. The newgrp command is useful in this situation. Before any users put files into the _share_ directory, they can run the command **newgrp share**. This switches their primary group to **share** so all files they put into the directory will automatically have the group **share**, rather than the user's primary group. Once they are finished, users can switch back to their regular primary group with (for example):
|
||||
|
||||
|
||||
```
|
||||
`newgrp alan`
|
||||
```
|
||||
|
||||
### Conclusion
|
||||
|
||||
It is important to understand how to manage users, groups, and permissions. It is also good to know a few alternative ways to work around problems you might encounter since not all environments are set up the same way.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/9/linux-chgrp-and-newgrp-commands
|
||||
|
||||
作者:[Alan Formy-Duval][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/alanfdosshttps://opensource.com/users/sethhttps://opensource.com/users/alanfdosshttps://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/community-penguins-osdc-lead.png?itok=BmqsAF4A (Penguins walking on the beach )
|
||||
[2]: https://opensource.com/article/19/8/linux-chown-command
|
||||
[3]: https://opensource.com/article/19/8/linux-chmod-command
|
@ -0,0 +1,76 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (3 open source social platforms to consider)
|
||||
[#]: via: (https://opensource.com/article/19/9/open-source-social-networks)
|
||||
[#]: author: (Jaouhari Youssef https://opensource.com/users/jaouharihttps://opensource.com/users/danarelhttps://opensource.com/users/osmomjianhttps://opensource.com/users/dff)
|
||||
|
||||
3 open source social platforms to consider
|
||||
======
|
||||
A photo-sharing platform, a privacy-friendly social network, and a web
|
||||
application for building and sharing portfolios.
|
||||
![Hands holding a mobile phone with open on the screen][1]
|
||||
|
||||
It is no mystery why modern social media platforms were designed to be addictive: the more we consult them, the more data they have to fuel them—which enables them to grow smarter and bigger and more powerful.
|
||||
|
||||
The massive, global interest in these platforms has created the attention economy, and people's focused mental engagement is the new gold in the age of information abundance. As economist, political scientist, and cognitive psychologist Herbert A. Simon said in [_Designing organizations for an information-rich world_][2], "the wealth of information means a dearth of something else: a scarcity of whatever it is that information consumes." And information consumes our attention, a resource we only have so much of it.
|
||||
|
||||
According to [GlobalWebIndex][3], we are now spending an average of 142 minutes on social media and messaging platforms daily, 63% more than the 90 minutes we spent on these platforms just seven years ago. This can be explained by the fact that these platforms have grown more intelligent over time by studying the minds and behaviors of users and applying those findings to boost their appeal.
|
||||
|
||||
Of relevance here is the psychological concept [variable-ratio schedule][4], which gives rewards after an average number of responses but on an unpredictable schedule. One example is slot machines, which may provide a reward an average of every five games, but the players don't know the specific number of games (one, two, seven, or even 15) they must play before obtaining a reward. This schedule leads to a high response rate and strong engagement.
|
||||
|
||||
Knowing all of this, what can we do to make things better and loosen the grip social networks have on us and our data? I suggest the answer is migrating to open source social platforms, which I believe consider the humane aspect of technology more than private companies do. Here are three open source social platforms to consider.
|
||||
|
||||
### Pixelfed
|
||||
|
||||
[Pixelfed][5] is a photo-sharing platform that is ad-free and privacy-focused, which means no third party is making a profit from your data. Posts are in chronological order, which means there is no algorithm making distinctions between content.
|
||||
|
||||
To join the network, you can pick one of the servers on the [list of instances][6], or you can [install and run][7] your own Pixelfed instance.
|
||||
|
||||
Once you are set up, you can connect with other Pixelfed instances. This is known as federation, which means many instances of a software (in this case, Pixelfed) share data (in this case, pictures). When you federate with another instance of Pixelfed, you can see and interact with pictures posted to other accounts.
|
||||
|
||||
The project is ongoing and needs the community's support to grow. Check [Pixelfed's GitHub][8] page for more information about contributing.
|
||||
|
||||
### Okuna
|
||||
|
||||
[Okuna][9] is an open source, privacy-friendly social network. It is committed to being a positive influence on society and the environment, plus it donates 30% of its profits to worthy causes.
|
||||
|
||||
### Mahara
|
||||
|
||||
[Mahara][10] is an open source web application for building and sharing electronic portfolios. (The word _mahara_ is Māori for _memory_ or _thoughtful consideration_.) With Mahara, you can create a meaningful and verifiable professional profile, but all your data belongs to you rather than a corporate sponsor. It is customizable and can be integrated into other web services.
|
||||
|
||||
You can try Mahara on its [demo site][11].
|
||||
|
||||
### Engage for change
|
||||
|
||||
If you want to know more about the impact of the attention economy on our lives and engage for positive change, take a look at the [Center for Humane Technology][12], an organization trying to temper the attention economy and make technology more humane. Its aim is to spur change that will protect human vulnerabilities from being exploited and therefore build a better society.
|
||||
|
||||
As Sonya Parker said, "whatever you focus your attention on will become important to you even if it's unimportant." So let's focus our attention on building a better world for all.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/9/open-source-social-networks
|
||||
|
||||
作者:[Jaouhari Youssef][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/jaouharihttps://opensource.com/users/danarelhttps://opensource.com/users/osmomjianhttps://opensource.com/users/dff
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/rh_003588_01_rd3os.combacktoschoolserieshe_rh_041x_0.png?itok=tfg6_I78 (Hands holding a mobile phone with open on the screen)
|
||||
[2]: https://digitalcollections.library.cmu.edu/awweb/awarchive?type=file&item=33748
|
||||
[3]: https://www.digitalinformationworld.com/2019/01/how-much-time-do-people-spend-social-media-infographic.html
|
||||
[4]: https://dictionary.apa.org/variable-ratio-schedule
|
||||
[5]: https://pixelfed.org/
|
||||
[6]: https://pixelfed.org/join
|
||||
[7]: https://docs.pixelfed.org/installing-pixelfed/
|
||||
[8]: https://github.com/pixelfed/pixelfed
|
||||
[9]: https://www.okuna.io/en/home
|
||||
[10]: https://mahara.org/
|
||||
[11]: https://demo.mahara.org/
|
||||
[12]: https://humanetech.com/problem/
|
@ -0,0 +1,258 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: ( )
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Mutation testing by example: Evolving from fragile TDD)
|
||||
[#]: via: (https://opensource.com/article/19/9/mutation-testing-example-definition)
|
||||
[#]: author: (Alex Bunardzic https://opensource.com/users/alex-bunardzichttps://opensource.com/users/alex-bunardzichttps://opensource.com/users/marcobravo)
|
||||
|
||||
Mutation testing by example: Evolving from fragile TDD
|
||||
======
|
||||
Test-driven development is not enough for delivering lean code that
|
||||
works exactly to expectations. Mutation testing is a powerful step
|
||||
forward. Here's what that looks like.
|
||||
![Binary code on a computer screen][1]
|
||||
|
||||
The [third article][2] in this series demonstrated how to use failure and unit testing to develop better code.
|
||||
|
||||
While it seemed that the journey was over with a successful sample Internet of Things (IoT) application to control a cat door, experienced programmers know that solutions need _mutation_.
|
||||
|
||||
### What's mutation testing?
|
||||
|
||||
Mutation testing is the process of iterating through each line of implemented code, mutating that line, then running unit tests and checking if the mutation broke the expectations. If it hasn't, you have created a surviving mutant.
|
||||
|
||||
Surviving mutants are always an alarming issue that points to potentially risky areas in a codebase. As soon as you catch a surviving mutant, you must kill it. And the only way to kill a surviving mutant is to create additional descriptions—new unit tests that describe your expectations regarding the output of your function or module. In the end, you deliver a lean, mean solution that is airtight and guarantees no pesky bugs or defects are lurking in your codebase.
|
||||
|
||||
If you leave surviving mutants to kick around and proliferate, live long, and prosper, then you are creating the much dreaded technical debt. On the other hand, if any unit test complains that the temporarily mutated line of code produces output that's different from the expected output, the mutant has been killed.
|
||||
|
||||
### Installing Stryker
|
||||
|
||||
The quickest way to try mutation testing is to leverage a dedicated framework. This example uses [Stryker][3].
|
||||
|
||||
To install Stryker, go to the command line and run:
|
||||
|
||||
|
||||
```
|
||||
`$ dotnet tool install -g dotnet-stryker`
|
||||
```
|
||||
|
||||
To run Stryker, navigate to the **unittest** folder and type:
|
||||
|
||||
|
||||
```
|
||||
`$ dotnet-stryker`
|
||||
```
|
||||
|
||||
Here is Stryker's report on the quality of our solution:
|
||||
|
||||
|
||||
```
|
||||
14 mutants have been created. Each mutant will now be tested, this could take a while.
|
||||
|
||||
Tests progress | 14/14 | 100% | ~0m 00s |
|
||||
Killed : 13
|
||||
Survived : 1
|
||||
Timeout : 0
|
||||
|
||||
All mutants have been tested, and your mutation score has been calculated
|
||||
\- \app [13/14 (92.86%)]
|
||||
[...]
|
||||
```
|
||||
|
||||
The report says:
|
||||
|
||||
* Stryker created 14 mutants
|
||||
* Stryker saw 13 mutants were killed by the unit tests
|
||||
* Stryker saw one mutant survive the onslaught of the unit tests
|
||||
* Stryker calculated that the existing codebase contains 92.86% of code that serves the expectations
|
||||
* Stryker calculated that 7.14% of the codebase contains code that does not serve the expectations
|
||||
|
||||
|
||||
|
||||
Overall, Stryker claims that the application assembled in the first three articles in this series failed to produce a reliable solution.
|
||||
|
||||
### How to kill a mutant
|
||||
|
||||
When software developers encounter surviving mutants, they typically reach for the implemented code and look for ways to modify it. For example, in the case of the sample application for cat door automation, change the line:
|
||||
|
||||
|
||||
```
|
||||
`string trapDoorStatus = "Undetermined";`
|
||||
```
|
||||
|
||||
to:
|
||||
|
||||
|
||||
```
|
||||
`string trapDoorStatus = "";`
|
||||
```
|
||||
|
||||
and run Stryker again. A mutant has survived:
|
||||
|
||||
|
||||
```
|
||||
All mutants have been tested, and your mutation score has been calculated
|
||||
\- \app [13/14 (92.86%)]
|
||||
[...]
|
||||
[Survived] String mutation on line 4: '""' ==> '"Stryker was here!"'
|
||||
[...]
|
||||
```
|
||||
|
||||
This time, you can see that Stryker mutated the line:
|
||||
|
||||
|
||||
```
|
||||
`string trapDoorStatus = "";`
|
||||
```
|
||||
|
||||
into:
|
||||
|
||||
|
||||
```
|
||||
`string trapDoorStatus = ""Stryker was here!";`
|
||||
```
|
||||
|
||||
This is a great example of how Stryker works: it mutates every line of our code, in a smart way, in order to see if there are further test cases we have yet to think about. It's forcing us to consider our expectations in greater depth.
|
||||
|
||||
Defeated by Stryker, you can attempt to improve the implemented code by adding more logic to it:
|
||||
|
||||
|
||||
```
|
||||
public string Control(string dayOrNight) {
|
||||
string trapDoorStatus = "Undetermined";
|
||||
if(dayOrNight == "Nighttime") {
|
||||
trapDoorStatus = "Cat trap door disabled";
|
||||
} else if(dayOrNight == "Daylight") {
|
||||
trapDoorStatus = "Cat trap door enabled";
|
||||
} else {
|
||||
trapDoorStatus = "Undetermined";
|
||||
}
|
||||
return trapDoorStatus;
|
||||
}
|
||||
```
|
||||
|
||||
But after running Stryker again, you see this attempt created a new mutant:
|
||||
|
||||
|
||||
```
|
||||
ll mutants have been tested, and your mutation score has been calculated
|
||||
\- \app [13/15 (86.67%)]
|
||||
[...]
|
||||
[Survived] String mutation on line 4: '"Undetermined"' ==> '""'
|
||||
[...]
|
||||
[Survived] String mutation on line 10: '"Undetermined"' ==> '""'
|
||||
[...]
|
||||
```
|
||||
|
||||
![Stryker report][4]
|
||||
|
||||
You cannot wiggle out of this tight spot by modifying the implemented code. It turns out the only way to kill surviving mutants is to _describe additional expectations_. And how do you describe expectations? By writing unit tests.
|
||||
|
||||
### Unit testing for success
|
||||
|
||||
It's time to add a new unit test. Since the surviving mutant is located on line 4, you realize you have not specified expectations for the output with value "Undetermined."
|
||||
|
||||
Let's add a new unit test:
|
||||
|
||||
|
||||
```
|
||||
[Fact]
|
||||
public void GivenIncorrectTimeOfDayReturnUndetermined() {
|
||||
var expected = "Undetermined";
|
||||
var actual = catTrapDoor.Control("Incorrect input");
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
```
|
||||
|
||||
The fix worked! Now all mutants are killed:
|
||||
|
||||
|
||||
```
|
||||
All mutants have been tested, and your mutation score has been calculated
|
||||
\- \app [14/14 (100%)]
|
||||
[Killed] [...]
|
||||
```
|
||||
|
||||
You finally have a complete solution, including a description of what is expected as output if the system receives incorrect input values.
|
||||
|
||||
### Mutation testing to the rescue
|
||||
|
||||
Suppose you decide to over-engineer a solution and add this method to the **FakeCatTrapDoor**:
|
||||
|
||||
|
||||
```
|
||||
private string getTrapDoorStatus(string dayOrNight) {
|
||||
string status = "Everything okay";
|
||||
if(dayOrNight != "Nighttime" || dayOrNight != "Daylight") {
|
||||
status = "Undetermined";
|
||||
}
|
||||
return status;
|
||||
}
|
||||
```
|
||||
|
||||
Then replace the line 4 statement:
|
||||
|
||||
|
||||
```
|
||||
`string trapDoorStatus = "Undetermined";`
|
||||
```
|
||||
|
||||
with:
|
||||
|
||||
|
||||
```
|
||||
`string trapDoorStatus = getTrapDoorStatus(dayOrNight);`
|
||||
```
|
||||
|
||||
When you run unit tests, everything passes:
|
||||
|
||||
|
||||
```
|
||||
Starting test execution, please wait...
|
||||
|
||||
Total tests: 5. Passed: 5. Failed: 0. Skipped: 0.
|
||||
Test Run Successful.
|
||||
Test execution time: 2.7191 Seconds
|
||||
```
|
||||
|
||||
The test has passed without an issue. TDD has worked. But bring Stryker to the scene, and suddenly the picture looks a bit grim:
|
||||
|
||||
|
||||
```
|
||||
All mutants have been tested, and your mutation score has been calculated
|
||||
\- \app [14/20 (70%)]
|
||||
[...]
|
||||
```
|
||||
|
||||
Stryker created 20 mutants; 14 mutants were killed, while six mutants survived. This lowers the success score to 70%. This means only 70% of our code is there to fulfill the described expectations. The other 30% of the code is there for no clear reason, which puts us at risk of misuse of that code.
|
||||
|
||||
In this case, Stryker helps fight the bloat. It discourages the use of unnecessary and convoluted logic because it is within the crevices of such unnecessary complex logic where bugs and defects breed.
|
||||
|
||||
### Conclusion
|
||||
|
||||
As you've seen, mutation testing ensures that no uncertain fact goes unchecked.
|
||||
|
||||
You could compare Stryker to a chess master who is thinking of all possible moves to win a match. When Stryker is uncertain, it's telling you that winning is not yet a guarantee. The more unit tests we record as facts, the further we are in our match, and the more likely Stryker can predict a win. In any case, Stryker helps detect losing scenarios even when everything looks good on the surface.
|
||||
|
||||
It is always a good idea to engineer code properly. You've seen how TDD helps in that regard. TDD is especially useful when it comes to keeping your code extremely modular. However, TDD on its own is not enough for delivering lean code that works exactly to expectations. Developers can add code to an already implemented codebase without first describing the expectations. That puts the entire code base at risk. Mutation testing is especially useful in catching breaches in the regular test-driven development (TDD) cadence. You need to mutate every line of implemented code to be certain no line of code is there without a specific reason.
|
||||
|
||||
Now that you understand how mutation testing works, you should look into how to leverage it. Next time, I'll show you how to put mutation testing to good use when tackling more complex scenarios. I will also introduce more agile concepts to see how DevOps culture can benefit from maturing technology.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/9/mutation-testing-example-definition
|
||||
|
||||
作者:[Alex Bunardzic][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/alex-bunardzichttps://opensource.com/users/alex-bunardzichttps://opensource.com/users/marcobravo
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/binary_code_computer_screen.png?itok=7IzHK1nn (Binary code on a computer screen)
|
||||
[2]: https://opensource.com/article/19/9/mutation-testing-example-part-3-execute-test
|
||||
[3]: https://stryker-mutator.io/
|
||||
[4]: https://opensource.com/sites/default/files/uploads/strykerreport.png (Stryker report)
|
@ -0,0 +1,136 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (geekpi)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (Introduction to the Linux chgrp and newgrp commands)
|
||||
[#]: via: (https://opensource.com/article/19/9/linux-chgrp-and-newgrp-commands)
|
||||
[#]: author: (Alan Formy-Duval https://opensource.com/users/alanfdosshttps://opensource.com/users/sethhttps://opensource.com/users/alanfdosshttps://opensource.com/users/seth)
|
||||
|
||||
Linux chgrp 和 newgrp 命令简介
|
||||
======
|
||||
chgrp 和 newgrp 命令可帮助你管理需要维护组所有权的文件。
|
||||
![Penguins walking on the beach ][1]
|
||||
|
||||
在最近的一篇文章中,我介绍了 [chown][2] 命令,它用于修改系统上的文件所有权。回想一下,所有权是分配一个对象的用户和组的组合。**chgrp** 和 **newgrp** 命令为管理需要维护组所有权的文件提供了帮助。
|
||||
|
||||
### 使用 chgrp
|
||||
|
||||
**chgrp** 只是更改文件的组所有权。这与 **chown :<group>** 命令相同。你可以使用:
|
||||
|
||||
|
||||
```
|
||||
`$chown :alan mynotes`
|
||||
```
|
||||
|
||||
或者:
|
||||
|
||||
|
||||
```
|
||||
`$chgrp alan mynotes`
|
||||
```
|
||||
|
||||
#### 递归
|
||||
|
||||
chgrp 的一些其他参数在命令行和脚本中都可能有用。就像许多其他 Linux 命令一样,chgrp 有一个递归参数 **-R**。如下所示,你需要它来对文件夹及其内容进行递归操作。我加了 **-v**(**verbose**)参数,因此 chgrp 会告诉我它在做什么:
|
||||
|
||||
|
||||
```
|
||||
$ ls -l . conf
|
||||
.:
|
||||
drwxrwxr-x 2 alan alan 4096 Aug 5 15:33 conf
|
||||
|
||||
conf:
|
||||
-rw-rw-r-- 1 alan alan 0 Aug 5 15:33 conf.xml
|
||||
# chgrp -vR delta conf
|
||||
changed group of 'conf/conf.xml' from alan to delta
|
||||
changed group of 'conf' from alan to delta
|
||||
```
|
||||
|
||||
#### 引用
|
||||
|
||||
引用文件 (**\--reference=RFILE**) 可用于更改匹配特定配置的文件的组,或者当你不知道组,比如你运行一个脚本时。你可以复制另外一个文件的组 (**RFILE**)。比如,为了撤销上面的更改 (请注意,点 [**.**] 指向当前工作目录):
|
||||
|
||||
```
|
||||
`$ chgrp -vR --reference=. conf`
|
||||
```
|
||||
|
||||
#### 报告更改
|
||||
|
||||
大多数命令都有用于控制其输出的参数。最常见的是 **-v** 来启用详细信息,并且 chgrp 命令拥有详细模式。它还具有 **-c**(**\--changes**)参数,表示 chgrp 仅在进行更改时报告。chgrp 还能报告其他内容,例如是否有不允许的操作。
|
||||
|
||||
参数 **-f**(**\--silent**、**\--quiet**)用于禁止显示大部分错误消息。我将在下一节中使用此参数和 **-c** 来显示实际更改。
|
||||
|
||||
#### 保留根目录
|
||||
|
||||
Linux 文件系统的根目录 (** / **) 应该受到高度重视。如果命令在此犯了一个错误,那么后果可能是可怕的,并会让系统无法使用。尤其是在运行一个会递归修改甚至删除的命令时。chgrp 命令有一个可用于保护和保留根目录的参数。它是 **\--preserve-root**。如果在根目录中将此参数和递归一起使用,那么什么也不会发生,而是会出现一条消息:
|
||||
|
||||
|
||||
```
|
||||
[root@localhost /]# chgrp -cfR --preserve-root a+w /
|
||||
chgrp: it is dangerous to operate recursively on '/'
|
||||
chgrp: use --no-preserve-root to override this failsafe
|
||||
```
|
||||
|
||||
不与递归结合使用时,该选项无效。但是,如果该命令由 root 用户运行,那么 **/** 的权限将会更改,但其中的其他文件或目录的权限则不会被更改:
|
||||
|
||||
|
||||
```
|
||||
[alan@localhost /]$ chgrp -c --preserve-root alan /
|
||||
chgrp: changing group of '/': Operation not permitted
|
||||
[root@localhost /]# chgrp -c --preserve-root alan /
|
||||
changed group of '/' from root to alan
|
||||
```
|
||||
|
||||
令人惊讶的是,它似乎不是默认参数。选项 **\--no-preserve-root** 是默认的。如果你在不带 “preserve” 选项的情况下运行上述命令,那么它将默认为“无保留”模式,并可能会更改不应更改的文件的权限:
|
||||
|
||||
|
||||
```
|
||||
[alan@localhost /]$ chgrp -cfR alan /
|
||||
changed group of '/dev/pts/0' from tty to alan
|
||||
changed group of '/dev/tty2' from tty to alan
|
||||
changed group of '/var/spool/mail/alan' from mail to alan
|
||||
```
|
||||
|
||||
### 关于 newgrp
|
||||
|
||||
**newgrp** 命令允许用户覆盖当前的主要组。当你在所有文件必须有相同组所有权的目录中操作时,newgrp 会很方便。假设你的内网服务器上有一个名为 _share_ 的目录,不同的团队在其中存储营销照片。组名为 “share”。当不同的用户将文件放入目录时,文件的主要组可能会变得混乱。每当添加新文件时,你都可以运行 **chgrp** 将错乱的组纠正为 **share**:
|
||||
|
||||
|
||||
```
|
||||
$ cd share
|
||||
ls -l
|
||||
-rw-r--r--. 1 alan share 0 Aug 7 15:35 pic13
|
||||
-rw-r--r--. 1 alan alan 0 Aug 7 15:35 pic1
|
||||
-rw-r--r--. 1 susan delta 0 Aug 7 15:35 pic2
|
||||
-rw-r--r--. 1 james gamma 0 Aug 7 15:35 pic3
|
||||
-rw-rw-r--. 1 bill contract 0 Aug 7 15:36 pic4
|
||||
```
|
||||
|
||||
我在 [**chmod** 命令][3]的文章中介绍了 **setgid**模式。它是解决此问题的一种方法。但是,假设由于某种原因未设置 setgid 位。newgrp 命令在此时很有用。在任何用户将文件放入 _share_ 目录之前,他们可以运行命令 **newgrp share**。这会将其主要组切换为 “share”,因此他们放入目录中的所有文件都将有 “share” 组,而不是用户的主要组。完成后,用户可以使用以下命令切换回常规主要组:
|
||||
|
||||
|
||||
```
|
||||
`newgrp alan`
|
||||
```
|
||||
|
||||
### 总结
|
||||
|
||||
了解如何管理用户、组和权限非常重要。最好知道一些替代方法来解决可能遇到的问题,因为并非所有环境都以相同的方式设置。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/19/9/linux-chgrp-and-newgrp-commands
|
||||
|
||||
作者:[Alan Formy-Duval][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[geekpi](https://github.com/geekpi)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/alanfdosshttps://opensource.com/users/sethhttps://opensource.com/users/alanfdosshttps://opensource.com/users/seth
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/community-penguins-osdc-lead.png?itok=BmqsAF4A (Penguins walking on the beach )
|
||||
[2]: https://opensource.com/article/19/8/linux-chown-command
|
||||
[3]: https://opensource.com/article/19/8/linux-chmod-command
|
Loading…
Reference in New Issue
Block a user