亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用資源鎖進行并行測試?

使用資源鎖進行并行測試?

慕姐4208626 2023-01-05 10:03:55
背景:現在使用java JUnit4,愿意遷移到JUnit5或TestNG。當前狀態:擁有 100 多個 Selenium 測試。其中大部分通過 Junit4 中的 @RunWith(Parameterized.class) 重復。(即根據提供的參數集創建測試類的多個實例,通常是瀏覽器類型 + 用戶身份的組合。)共享大約 12 個用戶的有限集合。限制:被測試的應用程序阻止同一用戶同時在多個地方登錄。因此,如果用戶在一個線程中運行的某個測試中登錄應用程序,則會導致同一用戶在同一時刻在另一個線程中運行的另一個測試中立即注銷。問題:當并行執行的測試無法共享某些資源時,是否有任何推薦的方法來管理線程安全?或者如何強制使用相同資源的那些測試在同一個線程中執行?感謝您的想法。這是到目前為止我用 TestNG 找到的一些解決方案的簡化示例......:public abstract class BaseTestCase {    protected static ThreadLocal<WebDriver> threadLocalDriver = new ThreadLocal<>();    protected String testUserName;    private static final Set<String> inUse = new HashSet<>();    public BaseTestCase(WebDriver driver, String testUserName) {        threadLocalDriver.set(driver);        this.testUserName = testUserName;    }    private boolean syncedAddUse(@NotNull String key){        synchronized (inUse){            return inUse.add(key);        }    }    private boolean syncedRemoveUse(@NotNull String key){        synchronized (inUse) {            return inUse.remove(key);        }    }    @DataProvider(parallel = true)    public static Object[][] provideTestData() {        //load pairs WebDriver+user from config file. E.g.:        //Chrome + chromeUser        //Chrome + chromeAdmin        //Firefox + firefoxUser        //etc...    }    @BeforeMethod    public void syncPoint() throws InterruptedException {        while( !syncedAddUse(testUserName) ){            //Waiting due the testUserName is already in use at the moment.            Thread.sleep(1000);        }    }    @AfterMethod    public void leaveSyncPoint(){        syncedRemoveUse(testUserName);    }}
查看完整描述

1 回答

?
守著一只汪

TA貢獻1872條經驗 獲得超4個贊

我不知道有什么方法可以在每個組都在一個線程中運行的組中組織測試。但是您可以用“嘗試鎖定用戶”替換“用戶忙時睡眠”。一旦對用戶完成另一個測試(即解鎖鎖),后者就會繼續執行。


下面的可運行示例應該讓您開始了解“嘗試鎖定用戶”的想法。請記住,如果您獲得了鎖(在您的情況下為“beforeTest”),您必須確保在“finally”塊(在您的情況下為“afterTest”)中釋放鎖。否則執行可能會掛起并且永遠不會完成。


import java.util.Map;

import java.util.Random;

import java.util.concurrent.ConcurrentHashMap;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.locks.ReentrantLock;

import java.util.concurrent.TimeUnit;

import java.util.stream.IntStream;


// https://stackoverflow.com/questions/56474713/parallel-tests-with-resource-lock

public class NamedResourceLocks {


    public static void main(String[] args) {


        System.out.println("Starting");

        ExecutorService executor = Executors.newCachedThreadPool();

        try {

            new NamedResourceLocks().run(executor);

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            executor.shutdownNow();

        }

        System.out.println("Done");

    }


    final static String userPrefix = "user";

    final static int maxUsers = 3;

    final static long maxWait = 10_000; // 10 seconds

    final static long startTime = System.currentTimeMillis();


    final Map<String, ReentrantLock> userLocks = new ConcurrentHashMap<>();

    final int maxTests = maxUsers * 10;

    final CountDownLatch allTestsDone = new CountDownLatch(maxTests);


    void run(ExecutorService executor) throws Exception {


        IntStream.range(0,  maxUsers).forEach(u -> 

            userLocks.put(userPrefix + u, new ReentrantLock(true)));

        IntStream.range(0,  maxTests).forEach(t -> 

            executor.execute(new Test(this, random.nextInt(maxUsers), t)));

        if (allTestsDone.await(maxWait, TimeUnit.MILLISECONDS)) {

            System.out.println("All tests finished");

        }

    }



    void lock(String user) throws Exception {


        ReentrantLock lock = userLocks.get(user);

        if (!lock.tryLock(maxWait, TimeUnit.MILLISECONDS)) {

            throw new RuntimeException("Waited too long.");

        }

    }


    void unlock(String user) {


        userLocks.get(user).unlock();

    }


    void oneTestDone() {


        allTestsDone.countDown();

    }


    final static Random random = new Random();


    static class Test implements Runnable {


        final NamedResourceLocks locks;

        final String user;

        final int testNumber;


        public Test(NamedResourceLocks locks, int userNumber, int testNumber) {

            this.locks = locks;

            this.user = userPrefix + userNumber;

            this.testNumber = testNumber;

        }


        @Override

        public void run() {


            boolean haveLock = false;

            try {

                log(this, "acquiring lock");

                locks.lock(user);

                haveLock = true;

                int sleepTime = random.nextInt(maxUsers) + 1; 

                log(this, "sleeping for " + sleepTime + " ms.");

                Thread.sleep(sleepTime);

            } catch (Exception e) {

                e.printStackTrace();

            } finally {

                if (haveLock) {

                    log(this, "releasing lock");

                    locks.unlock(user);

                }

                locks.oneTestDone();

            }

        }


    }


    static void log(Test test, String msg) {

        System.out.println((System.currentTimeMillis() - startTime) + " - " +

                test.testNumber + " / " + test.user + " - " + msg);

    }

}



查看完整回答
反對 回復 2023-01-05
  • 1 回答
  • 0 關注
  • 160 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號